抽象工厂模式
简介
抽象工厂模式:是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类。
抽象工厂定义了用于创建不同产品的接口, 但将实际的创建工作留给了具体工厂类。 每个工厂类型都对应一个特定的产品变体。
在创建产品时, 客户端代码调用的是工厂对象的构建方法, 而不是直接调用构造函数(new操作符)。 由于一个工厂对应一种产品变体, 因此它创建的所有产品都可相互兼容。
客户端代码仅通过其抽象接口与工厂和产品进行交互。 该接口允许同一客户端代码与不同产品进行交互。 你只需创建一个具体工厂类并将其传递给客户端代码即可。
例子
#父类
class Test:
#初始化
def __init__(self, n):
self.n = n
def say_hi(self):
print("hello")
#子类(继承自Test)
class Eg1(Test):
# 重写 Text 类中的 say_hi 方法 # 当该方法被调用时,它将打印字符串 #"first," 后跟实例变量 n 的值
def say_hi(self):
print(f'first,{self.n}')
class Eg2(Test):
def say_hi(self):
print(f'second,{self.n}')
class Eg3(Test):
def say_hi(self):
print(f'third,{self.n}')
class Eg4(Test):
def say_hi(self):
print(f'forth,{self.n}')
# 定义一个名为 AbstractFactory 的抽象类 # 抽象类可以包含抽象方法,这些#方法在子类中必须被实现
class AbstractFactory:
def create(self, t):
pass
# 定义一个名为 Factory 的类,它继承自 AbstractFactory 类
class Factory(AbstractFactory):
# 实现 AbstractFactory 类中的create方法 # 根据传入的参数 t,返回相应#的类实例
def create(self, t):
if t == 'a1':
return Eg1('p1')
elif t == 'b2':
return Eg2('p2')
elif t == 'c3':
return Eg3('p3')
elif t == 'd4':
return Eg4('p4')
else:
return None
# 创建工厂实例并使用它来创建对象
b1 = Factory().create('d4')
b1.say_hi()
打印如下图:
如何实现抽象工场模式
实现抽象工厂模式通常涉及以下几个步骤:
- 定义抽象产品接口:为每种产品类型定义一个接口或抽象类。
- 定义具体产品类:实现抽象产品接口,创建具体的产品类。
- 定义抽象工厂接口:声明创建抽象产品对象的操作。
- 定义具体工厂类:实现抽象工厂接口,创建并返回具体的产品对象。
- 客户端代码:使用抽象工厂和抽象产品接口进行编程,以创建并使用具体的产品对象。
抽象工厂模式的优缺点
优点:
- 封装性:抽象工厂模式将一组具有同一主题的单独工厂封装起来,在客户端不需要知道具体的实现类的情况下,就可以创建出相关的对象。
- 易于交换产品系列:由于具体工厂类的作用范围限制在抽象工厂内部,因此更换产品系列时只需要更换具体的工厂类即可,无需修改客户端代码。
- 增加新产品族很方便:增加新的产品族很方便,只需要增加具体的产品类和对应的工厂类即可,不需要修改已有系统代码。
- 符合开闭原则:抽象工厂模式符合开闭原则,因为当你想增加一个新系列的产品时,你不需要修改已有的代码,只需要添加新的具体产品和工厂类。
缺点:
- 难以扩展新产品:如果需要增加新的产品类型,所有的具体工厂类都需要进行修改,这违反了开闭原则。
- 类数量增加:由于需要为每个产品系列创建多个具体的工厂类和产品类,这可能会导致系统中类的数量增加,增加了系统的复杂性。
- 增加系统的抽象性和理解难度:抽象工厂模式引入了抽象层,这可能使得系统的理解更加困难,特别是对于那些不熟悉设计模式的开发者。
- 产品族扩展困难:如果产品族中需要增加新的产品,则需要修改抽象工厂的接口,这涉及到所有具体工厂类的修改,可能会导致较大的代码改动。
抽象工厂模式适合应用场景
- 系统需要处理多个产品族的情况:当你需要创建的对象是一系列相互关联或相互依赖的产品时,抽象工厂模式可以帮助你管理这些产品族。
- 系统需要独立于产品的创建、组合和表示时:抽象工厂模式允许你将创建逻辑封装起来,这样客户端代码就不需要知道具体的创建细节。
- 系统需要配置多种可能的产品组合时:通过抽象工厂,你可以定义多个工厂类,每个工厂类负责创建一组特定的产品组合。
- 例如,数据库连接(如果你需要支持多种数据库,每种数据库都有自己的连接方式、查询语句等,你可以使用抽象工厂模式来创建不同数据库的连接和操作对象。)、文档编辑器中的不同格式支持(一个文档编辑器可能需要支持多种文档格式(如PDF、Word、HTML等)。每种格式都有不同的组件(如字体、图像、段落等)。抽象工厂可以用来创建特定格式所需的组件。)