UML 统一建模语言

工厂模式

工厂模式就相当于用户不需要知道该调用哪个类来实例,只需要调用这个函数(方法),就可以生成出想要的对应的实例来。这样就解耦了对象的使用和创建。

工厂方法设计模式是实现一个不属于任何类的单一函数,负责单一种类对象的创建。

抽象工厂设计模式是同属于单个类的多个工厂方法用来实现创建一系列种类的相关对象。

工厂方法

执行单独的函数,通过传参提供需要的对象的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import json
import xml.etree.ElementTree as etree
class JSONConnector:
def __init__(self, filepath):
self.data = dict()
with open(filepath, mode='r', encoding='utf8') as f:
self.data = json.load(f)
@property
def parsed_data(self):
return self.data
class XMLConnector:
def __init__(self, filepath):
self.tree = etree.parse(filepath)
@property
def parsed_data(self):
return self.tree
def connection_factory(filepath):
""" 工厂方法 """
if filepath.endswith('json'):
connector = JSONConnector
elif filepath.endswith('xml'):
connector = XMLConnector
else:
raise ValueError('Cannot connect to {}'.format(filepath))
return connector(filepath)

抽象工厂

工厂方法适合对象种类比较少的情况,因为毕竟要对每个情况使用不同类会导致工厂方法十分臃肿。如果对于复杂情况,使用一个抽象工厂使用多个工厂方法来实现创建一系列种类的相关对象。然后有一个入口来接收抽象工厂作为输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class Frog:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
""" 不同类型玩家遇到的障碍不同 """
print('{} the Frog encounters {} and {}!'.format(
self, obstacle, obstacle.action()))
class Bug:
def __str__(self):
return 'a bug'
def action(self):
return 'eats it'
class FrogWorld:
"""
抽象工厂,不同的工厂方法创建了多个对象
"""
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t----Frog World -----'
def make_character(self):
return Frog(self.player_name)
def make_obstacle(self):
return Bug()
class Wizard:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
print('{} the Wizard battles against {} and {}!'.format(
self, obstacle, obstacle.action()))
class Ork:
def __str__(self):
return 'an evil ork'
def action(self):
return 'kill it'
class WizardWorld:
"""
抽象工厂
"""
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t------ Wizard World -------'
def make_character(self):
return Wizard(self.player_name)
def make_obstacle(self):
return Ork()
class GameEnvironment:
""" 根据不同的玩家类型创建不同的角色和障碍 (游戏环境)
这里可以根据年龄判断,成年人返回『巫师』游戏,小孩返回『青蛙过河』游戏"""
def __init__(self, factory):
self.hero = factory.make_character()
self.obstacle = factory.make_obstacle()
def play(self):
self.hero.interact_with(self.obstacle)

构造模式

复杂对象的构造,对象需要多个部分组合起来一步步创建。这个组合过程你可以传入builder从而自定义创建的方式。如果一个对象需要多个步骤创建,同一个构造过程可以产生不同的表现。工厂模式单个步骤创建对象,而构造模式以多个步骤创建对象。

对象的构造和表现解耦。建造者隐藏了该产品是如何组装的,所以如要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但是对象内部的构建通常面临着复杂的变化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# builder模式
class Computer:
def __init__(self, serial_number):
self.serial = serial_number
self.memory = None # in gigabytes
self.hdd = None # in gigabytes
self.gpu = None
def __str__(self):
info = ('Memory: {}GB'.format(self.memory),
'Hard Disk: {}GB'.format(self.hdd),
'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)
class ComputerBuilder:
def __init__(self):
self.computer = Computer('AG23385193')
def configure_memory(self, amount):
self.computer.memory = amount
def configure_hdd(self, amount):
self.computer.hdd = amount
def configure_gpu(self, gpu_model):
self.computer.gpu = gpu_model
class HardwareEngineer:
def __init__(self):
self.builder = None
def construct_computer(self, memory, hdd, gpu):
self.builder = ComputerBuilder()
[step for step in (self.builder.configure_memory(memory),
self.builder.configure_hdd(hdd),
self.builder.configure_gpu(gpu))]
@property
def computer(self):
return self.builder.computer
# 使用buidler,可以创建多个builder类实现不同的组装方式
# engineer就相当于一个指挥者
engineer = HardwareEngineer()
# 不同的创建顺序和步骤,后面的ComputerBuilder就是一个建造者,根据不同顺序来建造
engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti')
computer = engineer.computer
print(computer)

原型模式

可以使得对于同一个对象可以有多个副本,原型设计模式帮助创建对象的克隆,并且保持一个克隆的注册表。

也就是说,已经有了一个对象,但是需要创建这个对象的副本的时候,但是重建一个这样的对象又没有什么意义,这样就需要一个原型模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import copy
from collections import OrderedDict
class Book:
def __init__(self, name, authors, price, **rest):
'''Examples of rest: publisher, length, tags, publication
date'''
self.name = name
self.authors = authors
self.price = price # in US dollars
self.__dict__.update(rest)
def __str__(self):
mylist = []
ordered = OrderedDict(sorted(self.__dict__.items()))
for i in ordered.keys():
mylist.append('{}: {}'.format(i, ordered[i]))
if i == 'price':
mylist.append('$')
mylist.append('\n')
return ''.join(mylist)
class Prototype:
def __init__(self):
self.objects = {}
def register(self, identifier, obj):
self.objects[identifier] = obj
def unregister(self, identifier):
del self.objects[identifier]
def clone(self, identifier, **attr):
""" 实现对象拷贝 """
found = self.objects.get(identifier)
if not found:
raise ValueError('Incorrect object identifier: {}'.format(identifier))
obj = copy.deepcopy(found)
obj.__dict__.update(attr) # 实现拷贝时自定义更新
return obj
def main():
b1 = Book('The C Programming Language', ('Brian W. Kernighan', 'Dennis M.Ritchie'),
price=118, publisher='Prentice Hall', length=228, publication_date='1978-02-22',
tags=('C', 'programming', 'algorithms', 'data structures'))
prototype = Prototype()
cid = 'k&r-first'
prototype.register(cid, b1)
b2 = prototype.clone(cid, name='The C Programming Language (ANSI)', price=48.99, length=274,
publication_date='1988-04-01', edition=2)
for i in (b1, b2):
print(i)
print("ID b1 : {} != ID b2 : {}".format(id(b1), id(b2)))