一、说明
(一) 解决问题
抽象工厂是一种创建型设计模式,主要解决接口选择的问题。能够创建一系列相关的对象,而无需指定其具体类。
(二) 使用场景
系统中有多于一个的产品族,且这些产品族类的产品需实现同样的接口。
例如:有一个家具工厂,可以生产的产品有椅子、沙发、咖啡桌,各产品又分为不同的风格。
而客户需要的是相同风格的各类产品
二、结构
- 抽象产品 (Abstract Product) 为构成系列产品的一组不同但相关的产品声明接口。
- 具体产品 (Concrete Product) 是抽象产品的多种不同类型实现。 所有变体 (维多利亚/现代) 都必须实现相应的抽象产品 (椅子/沙发)。
- 抽象工厂 (Abstract Factory) 接口声明了一组创建各种抽象产品的方法。
- 具体工厂 (Concrete Factory) 实现抽象工厂的构建方法。 每个具体工厂都对应特定产品变体, 且仅创建此种产品变体。
- 尽管具体工厂会对具体产品进行初始化, 其构建方法签名必须返回相应的抽象产品。 这样, 使用工厂类的客户端代码就不会与工厂创建的特定产品变体耦合。 客户端 (Client) 只需通过抽象接口调用工厂和产品对象, 就能与任何具体工厂/产品变体交互。
三、伪代码
python
__doc__ = """
抽象工厂模式
例:有一个家具工厂,可以生产的产品有椅子、沙发、咖啡桌,各产品又分为不同的风格。
"""
from abc import ABC, abstractmethod
class AbstractFactory(ABC):
"""
抽象工厂基类
提供创建三种家具抽象方法
"""
@abstractmethod
def create_chair(self):
pass
@abstractmethod
def create_sofa(self):
pass
@abstractmethod
def create_coffee_table(self):
pass
class ModernFactory(AbstractFactory):
"""
具体工厂基类
实现创建现代风格家具的方法
"""
def create_chair(self):
return ModernChair()
def create_sofa(self):
return ModernSofa()
def create_coffee_table(self):
return ModernCoffeeTable()
class VictorianFactory(AbstractFactory):
"""
具体工厂基类
实现创建维多利亚风格家具的方法
"""
def create_chair(self):
return VictorianChair()
def create_sofa(self):
return VictorianSofa()
def create_coffee_table(self):
return VictorianCoffeeTable()
class AbstractProduct(ABC):
"""
抽象产品基类
提供使用抽象方法
"""
@abstractmethod
def use(self):
pass
class ModernChair(AbstractProduct):
"""具体产品"""
def use(self):
print("现代风格椅子")
class ModernSofa(AbstractProduct):
"""具体产品"""
def use(self):
print("现代风格沙发")
class ModernCoffeeTable(AbstractProduct):
"""具体产品"""
def use(self):
print("现代风格咖啡桌")
class VictorianChair(AbstractProduct):
"""具体产品"""
def use(self):
print("维多利亚风格椅子")
class VictorianSofa(AbstractProduct):
"""具体产品"""
def use(self):
print("维多利亚风格沙发")
class VictorianCoffeeTable(AbstractProduct):
"""具体产品"""
def use(self):
print("维多利亚风格咖啡桌")
def client_code(factory):
"""客户端"""
chair = factory.create_chair()
sofa = factory.create_sofa()
coffee_table = factory.create_coffee_table()
chair.use()
sofa.use()
coffee_table.use()
if __name__ == '__main__':
"""
Client: Testing client code with the first factory type:
现代风格椅子
现代风格沙发
现代风格咖啡桌
Client: Testing the same client code with the second factory type:
维多利亚风格椅子
维多利亚风格沙发
维多利亚风格咖啡桌
"""
print("Client: Testing client code with the first factory type:")
factory1 = ModernFactory()
client_code(factory1)
print()
print("Client: Testing the same client code with the second factory type:")
factory2 = VictorianFactory()
client_code(factory2)
四、优缺点
优点
- 你可以确保同一工厂生成的产品相互匹配。
- 你可以避免客户端和具体产品代码的耦合。
- 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。
缺点
- 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。