创建型模式
创建型模式: 聚焦对象的创建.
对象的创建, 很容易想到 对象=类名(传参数)
, 使用创建型模式, 要把写类的人和创建对象的人看作两波人?!
如何理解, 我们一边学习 创建型模式 一边悟! (*≧ω≦)
# 简单工厂模式
简单工厂模式: 不直接想客户端暴露 [对象创建] 的细节.. 而是通过一个工厂类来负责创建产品类的实例!!
首先声明: 简单工厂模式不在23种设计里面, 但还是得明白它, 为后续的工厂方法模式、抽象工厂模式做铺垫.
class AliPay:
def __init__(self):
pass
def pay(self, money):
pass
class WechatPay:
def __init__(self):
pass
def pay(self, money):
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
Q: 我们现拥有上面这两个支付类, 直接 AliPay().pay(100)
、WechatPay().pay(100)
ok 不ok ?
A: 不ok.
支付宝支付可能有10-20个参数,微信支付可能有10-20个参数.
客户端调用,去揣摩这些参数?
客户端自己去了解AliPay、WechatPay这些类创建对象的__init__代码?
客户端自己去看哪些参数需要,哪些参数不需要?
这用起来很不舒服啊!!
☆ 解决方案:我们可以将这些参数隐藏到支付工厂的创建对象相关的creat_payment方法里!
- 像什么各个支付编码格式的不同、需要传时间戳用于生成订单id等操作都可以在create_payment方法中处理好!!
2
3
4
5
6
7
8
示例完整代码:
from abc import ABCMeta, abstractmethod
# -抽象产品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# -具体产品
class Alipay(Payment):
def __init__(self, use_huabei=False):
self.use_huabei = use_huabei
def pay(self, money):
if self.use_huabei:
print(f"花呗支付了{money}元!")
else:
print(f"支付宝余额支付了{money}元!")
# -具体产品
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付了{money}元!")
# -简单工厂类
class PaymentFactory:
def create_payment(self, method):
if method == 'Alipay':
return Alipay()
elif method == 'WechatPay':
return WechatPay()
elif method == 'HuabeiPay':
return Alipay(use_huabei=True)
else:
raise TypeError('No such payment named %s' % method)
# -客户端调用.
pf = PaymentFactory() # > 简单工厂类实例化
p = pf.create_payment('HuabeiPay') # > 创建产品的对象
p.pay(100) # 花呗支付了100元!
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
# 工厂方法模式
工厂方法模式: 定义一个用于创建产品对象的接口(工厂接口), 子类实现该接口时决定实例化哪一个产品类.
将简单工厂模式的那个工厂类拆分成了多个工厂类!!
当新增一个具体产品时, 只需写一个对应的工厂类即可, 已经存在的代码都不用动且已存在的代码逻辑肯定是对的.
■ 角色: 抽象工厂、具体工厂、抽象产品、具体产品
■ 优点:
1> 每个具体产品都对应一个工厂类, 新增产品时不用修改已有的工厂类代码.
2> 当客户端调用时, 隐藏了对象创建的实现细节!
■ 缺点: 每增加一个具体产品类, 就必须得增加一个相应的具体工厂类!!
简单工厂模式和工厂方法模式在现实生活中,用还是可以用的,比如:
- 你写了一个很复杂的类,该类又需要频繁的创建,因为参数很多,你不想让调用这个类对象的傻子出错.
就可以考虑用这两个模式封装一下下 Hhh
2
3
示例完整代码:
from abc import ABCMeta, abstractmethod
# -抽象产品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# -具体产品
class Alipay(Payment):
def __init__(self, use_huabei=False):
self.use_huabei = use_huabei
def pay(self, money):
if self.use_huabei:
print(f"花呗支付了{money}元!")
else:
print(f"支付宝余额支付了{money}元!")
# -具体产品
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付了{money}元!")
# -抽象工厂
class PaymentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
# -具体工厂
class AlipayFactory(PaymentFactory):
def create_payment(self):
return Alipay()
# -具体工厂
class WechatPayFactory(PaymentFactory):
def create_payment(self):
return Alipay()
# -具体工厂
class HuabeiFactory(PaymentFactory):
def create_payment(self):
return Alipay(use_huabei=True)
# -客户端调用.
pf = HuabeiFactory() # > 具体工厂类实例化
p = pf.create_payment() # > 创建具体产品的对象
p.pay(100) # 花呗支付了100元!
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
# 抽象工厂模式
抽象工厂模式 使用的很少.. 简单工厂模式和工厂方法模式使用的多一些.
抽象工厂模式: 定义一个工厂类接口, 让工厂子类来创建一些列相关或相互依赖的对象.
相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品.. -- 给这一套产品作限制: eg 华为手机不能是ios系统.
举个例子:
生产一部首,需要对手机壳、cpu、操作系统这三类对象进行封装, 其中每类对象都有不同的种类.
对每个具体工厂,分别生产一部手机所需要的三个对象.
■ 角色: 抽象工厂、具体工厂、抽象产品、具体产品、客户端
■ 优点:
1> 将客户端与类的具体实现相分离 => 所有的工厂模式都有这个特点.
2> 每个工厂创建了一个完整的产品系列,使得易于交互产品系列.. => eg: 小米用高通cpu,魅族也用高通cpu.
3> 有利于产品的一致性. => 即产品之间的约束关系.
■ 缺点: 难以支持新种类的(抽象)产品. eg: 除了手机壳、cpu、os之外, 再加一个屏幕, 就是4个为一套了,工厂类也要大改.
示例完整代码如下:
from abc import ABCMeta, abstractmethod
# ------抽象的产品------
class PhoneShell(metaclass=ABCMeta):
@abstractmethod
def show_shell(self):
pass
class PhoneCPU(metaclass=ABCMeta):
@abstractmethod
def show_cpu(self):
pass
class PhoneOS(metaclass=ABCMeta):
@abstractmethod
def show_os(self):
pass
# ------具体的产品------
class SmallShell(PhoneShell):
def show_shell(self):
print('普通手机小手机壳')
class BigShell(PhoneShell):
def show_shell(self):
print('普通手机大手机壳')
class AppleShell(PhoneShell):
def show_shell(self):
print('苹果手机壳')
class SnapDragonCPU(PhoneCPU):
def show_cpu(self):
print('骁龙CPU')
class HuaweiCPU(PhoneCPU):
def show_cpu(self):
print('化为CPU')
class AppleCPU(PhoneCPU):
def show_cpu(self):
print('苹果CPU')
class AndroidOS(PhoneOS):
def show_os(self):
print('IOS系统')
class AppleOS(PhoneOS):
def show_os(self):
print('安卓系统')
# ------抽象的工厂------
class PhoneFactory(metaclass=ABCMeta):
@abstractmethod
def make_shell(self):
pass
@abstractmethod
def make_cpu(self):
pass
@abstractmethod
def make_os(self):
pass
# ------具体的工厂------
class HuaweiFactory(PhoneFactory):
def make_shell(self):
return SmallShell()
def make_cpu(self):
return HuaweiCPU()
def make_os(self):
return AndroidOS()
class AppleFactory(PhoneFactory):
def make_shell(self):
return AppleShell()
def make_cpu(self):
return AppleCPU()
def make_os(self):
return AppleOS()
# ------高层代码/客户端------
class Phone:
def __init__(self, shell, cpu, os):
self.shell = shell
self.cpu = cpu
self.os = os
def show_info(self):
print('手机信息:')
self.shell.show_shell()
self.cpu.show_cpu()
self.os.show_os()
def make_phone(factory):
shell = factory.make_shell()
cpu = factory.make_cpu()
os = factory.make_os()
return Phone(shell, cpu, os)
# - 客户端调用过程
p = make_phone(HuaweiFactory())
p.show_info()
"""
手机信息:
普通手机小手机壳
化为CPU
IOS系统
"""
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 建造者模式
建造者模式: 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示.
建造者模式与抽象工厂模式相似,也用来创建复杂的对象..
★ 主要区别是, 建造者模式着重一步步构造一个复杂对象(控制顺序), 而抽象工厂模式着重于多个系列的产品对象..
说白了, 建造者模式每个具体工厂不仅是生产一套产品, 还要控制这一套产品的生产顺序..
■ 角色: 抽象建造者、具体建造者、指挥者、产品
■ 优点:
1> 隐藏了一个产品的内部结构和装配过程 => 内部结构指self.player.face='绿脸'; 装配过程指指挥者里的顺序
2> 将构造代码于表示代码分开 => 构造代码指指挥者; 表示代码指具体建造者
3> 可以对构造过程进行更精细的控制. => 即指挥者那部分代码,你想多精细就可多精细.
示例完整代码如下:
from abc import ABCMeta, abstractmethod
# ------产品,face、body、arms、legs都可看作是一个产品,这些产品可构造一个复杂对象------
class Player:
def __init__(self, face=None, body=None, arms=None, legs=None):
self.face = face
self.body = body
self.arms = arms
self.legs = legs
def __str__(self):
return '%s,%s,%s,%s' % (self.face, self.body, self.arms, self.legs)
# ------抽象建造者 > 对标抽象工厂------
class PlayerBuilder(metaclass=ABCMeta):
@abstractmethod
def build_face(self):
pass
@abstractmethod
def build_body(self):
pass
@abstractmethod
def build_arms(self):
pass
@abstractmethod
def build_legs(self):
pass
# ------具体建造者 > 对标具体工厂------
class GirlBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = '漂亮的脸蛋'
def build_body(self):
self.player.body = '苗条的身材'
def build_arms(self):
self.player.arms = '细细的胳膊'
def build_legs(self):
self.player.legs = '大长腿'
# ------具体建造者 > 对标具体工厂------
class MonsterBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = '绿脸'
def build_body(self):
self.player.body = '魁梧的身体'
def build_arms(self):
self.player.arms = '粗壮的胳膊'
def build_legs(self):
self.player.legs = '粗壮的大腿'
# ------指挥者 > 对标高层代码/客户端------
class PlayerDirectory():
def builder_player(self, builder):
builder.build_face()
builder.build_body()
builder.build_arms()
builder.build_legs()
return builder.player
# ------客户端使用过程------
builder = GirlBuilder()
director = PlayerDirectory()
p = director.builder_player(builder)
print(p) # 漂亮的脸蛋,苗条的身材,细细的胳膊,大长腿
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
# 单例模式
单例模式: 保证一个类里只有一个实例, 并提供一个访问它的全局访问点.