Python实现软件设计模式3:抽象工厂模式
特点
- 系统中除了有多种产品类型(产品等级结构,如果汁、方便面、矿泉水),还出现了多个品牌(产品族,或农夫山泉、娃哈哈、康师傅、统一等品牌几乎都有这些产品)
- 在工厂方法模式中,只有一个产品等级结构
- 一个抽象产品(父类)、多个具体产品(子类)形成一个产品等级结构
- 产品族是指由同一个工厂生产,位于不同产品等级结构的一组产品
角色组成
- 抽象工厂 Abstract Factory
- 具体工厂 Concrete Factory
- 抽象产品 Abstract Product
- 具体产品 Concrete Product
模式实例
电器工厂:一个电器工厂可以生产多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视机、TCL空调等,相同品牌的电器构成一个产品族,而向同类型的电器构成了一个产品等级结构。
代码实现
from abc import ABC,abstractmethod
class TV(ABC): # 抽象产品 1
@abstractmethod
def play(self):
pass
class AirConditioner(ABC): # 抽象产品 2
@abstractmethod
def changetemperature(self):
pass
class HaierTV(TV): # 具体产品
def play(self):
print("海尔电视播放中...")
class HuaweiTV(TV): # 具体产品
def play(self):
print("华为电视播放中...")
class HaierAirCon(AirConditioner): # 具体产品
def changetemperature(self):
print("海尔空调温度改变中!!!")
class HuaweiAirCon(AirConditioner): # 具体产品
def changetemperature(self):
print("华为空调温度改变中!!!")
class EFactory(ABC): # 抽象工厂
@abstractmethod
def produceTV(self):
pass
@abstractmethod
def produceAirCon(self):
pass
class HaierFactory(EFactory): # 具体产品族工厂1
def produceTV(self):
return HaierTV()
def produceAirCon(self):
return HaierAirCon()
class HuaweiFactory(EFactory): # 具体产品族工厂2
def produceTV(self):
return HuaweiTV()
def produceAirCon(self):
return HuaweiAirCon()
class Client: # 客户端
def __init__(self, FactoryName): # 传入工厂名称参数
self.factname = FactoryName
def run(self):
try:
factory = eval(self.factname)()
tv = factory.produceTV()
tv.play()
ac = factory.produceAirCon()
ac.changetemperature()
except NameError:
print(f"Error! Factory '{self.factname}' doesn't exits...")
if __name__ == '__main__':
f1 = Client('HuaweiFactory')
f1.run()
f2 = Client('HaierFactory')
f2.run()
总结
- 客户端始终只使用同一个产品族中的对象
- 增加新的产品族(品牌)很方便,无序修改已有系统源码,只需要新增已有抽象工厂的子类并在其中实现产品构造方法,符合开闭原则!
- 增加新的产品等级结构较麻烦,因为需要修改原有系统代码(所有工厂类,包括抽象工厂和具体品牌工厂),违背了开闭原则!
- 适合使用场景:一个系统不应该依赖于产品类实例如何被创建、组合和表达的细节;产品等级结构稳定,不会增加或删除已有的产品等级结构;系统中有多个产品族,但每次只使用其中某一个产品族