python设计模式:工厂模式

工厂模式,顾名思义就是我们可以通过一个指定的”工厂”获得需要的”产品”,在设计模式中主要用于抽象对象的创建过程,让用户可以指定自己想要的对象而不必关心对象的实例化过程,这样做的好处是用户只需通过固定的接口而不是直接去调用类的实例化方法来获得一个对象的实例,隐藏了实例创建过程的复杂度,解耦了生产实例和使用实例的代码,降低了维护的复杂性。

简单工厂

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
class Mercedes(object):
# 梅赛德斯
def __repr__(self):
return "Mercedes-Benz"

class BMW(object):
# 宝马
def __repr__(self):
return "BMW"

class SimpleCarFactory(object):
"""简单工厂
"""
@staticmethod
def product_car(name):
if name == 'mb':
return Mercedes()
elif name == 'bmw':
return BMW()


if __name__ == '__main__':
c1 = SimpleCarFactory.product_car('mb')
c2 = SimpleCarFactory.product_car('bmw')
print(c1, c2)

工厂方法

虽然有了一个简单的工厂,但在实际使用工厂的过程中,我们会发现新问题:如果我们要新增一个”产品”,例如Audi的汽车,我们除了新增一个Audi类外还要修改SimpleCarFactory内的product_car方法。这样就违背了软件设计中的开闭原则,即:在扩展新的类时,尽量不要修改原有代码。所以我们在简单工厂的基础上把SimpleCarFactory抽象成不同的工厂,让每个工厂对应生成自己的产品,这就是工厂方法。

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
import abc

class Mercedes(object):
# 梅赛德斯
def __repr__(self):
return "Mercedes-Benz"

class BMW(object):
# 宝马
def __repr__(self):
return "BMW"


class AbstractFactory(object):
# 抽象工厂
__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def product_car(self):
pass

class MercedesFactory(AbstractFactory):
# 梅赛德斯工厂
def product_car(self):
return Mercedes()

class BMWFactory(AbstractFactory):
# 宝马工厂
def product_car(self):
return BMW()

if __name__ == '__main__':
c1 = MercedesFactory().product_car()
c2 = BMWFactory().product_car()
print(c1)
print(c2)

使用工厂方法,在新增产品时不需要再修改工厂的代码而是增加相应的工厂即可。例如新增一个Audi产品,只需新增一个Audi类和AudiFactory类。

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
import abc

class Mercedes(object):
# 梅赛德斯
def __repr__(self):
return "Mercedes-Benz"

class BMW(object):
# 宝马
def __repr__(self):
return "BMW"

class Audi(object):
# 奥迪
def __repr__(self):
return "Audi"

class AbstractFactory(object):
# 抽象工厂
__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def product_car(self):
pass

class MercedesFactory(AbstractFactory):
# 梅赛德斯工厂
def product_car(self):
return Mercedes()

class BMWFactory(AbstractFactory):
# 宝马工厂
def product_car(self):
return BMW()

class AudiFactory(AbstractFactory):
# 奥迪工厂
def product_car(self):
return Audi()

if __name__ == '__main__':
c1 = MercedesFactory().product_car()
c2 = BMWFactory().product_car()
c3 = AudiFactory().product_car()
print(c1)
print(c2)
print(c3)

抽象工厂

工厂方法虽然解决了我们”修改代码”的问题,但如果我们要生产很多产品,就会需要写很多对应的工厂类。所以为了解决这个问题,我们就要再更进一步的抽象工厂类,让一个工厂可以生产同一类的多个产品,这就是抽象工厂。

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
import abc

# 两种小汽车
class Mercedes_C63(object):
# 梅赛德斯
def __repr__(self):
return "Mercedes-Benz: C63"

class BMW_M3(object):
# 宝马
def __repr__(self):
return "BMW: M3"

# 两种SUV
class Mercedes_G63(object):
# 梅赛德斯 G63
def __repr__(self):
return "Mercedes-Benz: G63"

class BMW_X5(object):
# 宝马 X5
def __repr__(self):
return "BMW: X5"

class AbstractFactory(object):
"""
抽象工厂
可以生产小汽车外,还可以生产SUV
"""
__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def product_car(self):
pass

@abc.abstractmethod
def product_suv(self):
pass

class MercedesFactory(AbstractFactory):
# 梅赛德斯工厂
def product_car(self):
return Mercedes_C63()

def product_suv(self):
return Mercedes_G63()

class BMWFactory(AbstractFactory):
# 宝马工厂
def product_car(self):
return BMW_M3()

def product_suv(self):
return BMW_X5()


if __name__ == '__main__':
c1 = MercedesFactory().product_car()
s1 = MercedesFactory().product_suv()
print(c1, s1)
s2 = BMWFactory().product_suv()
c2 = BMWFactory().product_car()
print(c2, s2)