Python设计模式:工厂模式
1. 什么是工厂模式?
工厂模式是一种创建对象的设计模式,它提供了一种创建对象的接口,但不暴露对象创建的具体逻辑。工厂模式的核心思想是将对象的创建与使用分离,从而提高代码的灵活性和可维护性。
1.1 工厂模式的类型
1.1.1 简单工厂模式(Simple Factory Pattern)
简单工厂模式通过一个工厂类来创建不同类型的对象。工厂类根据传入的参数决定创建哪种类型的对象。这种模式并不属于 GoF 设计模式中的 23 种设计模式,但在实际应用中非常常见。
# 产品接口
class Product:
def operation(self):
pass
# 具体产品类
class ConcreteProductA(Product):
def operation(self):
return "Result of ConcreteProductA"
class ConcreteProductB(Product):
def operation(self):
return "Result of ConcreteProductB"
# 工厂类
class SimpleFactory:
@staticmethod
def create_product(product_type):
if product_type == "A":
return ConcreteProductA()
elif product_type == "B":
return ConcreteProductB()
else:
raise ValueError("Unknown product type")
# 客户端代码
if __name__ == "__main__":
factory = SimpleFactory()
product_a = factory.create_product("A")
print(product_a.operation()) # 输出: Result of ConcreteProductA
product_b = factory.create_product("B")
print(product_b.operation()) # 输出: Result of ConcreteProductB
- 产品接口:定义了一个产品接口
Product
,具体产品类ConcreteProductA
和ConcreteProductB
实现了该接口。 - 工厂类:
SimpleFactory
类提供了一个静态方法create_product
,根据传入的参数创建不同类型的产品。 - 客户端代码:在客户端代码中,使用工厂类创建产品对象,而不需要直接依赖具体的产品类。
1.1.2 工厂方法模式(Factory Method Pattern)
工厂方法模式定义一个创建对象的接口,但由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。这种模式允许用户在不修改现有代码的情况下引入新产品。
# 产品接口
class Product:
def operation(self):
pass
# 具体产品类
class ConcreteProductA(Product):
def operation(self):
return "Result of ConcreteProductA"
class ConcreteProductB(Product):
def operation(self):
return "Result of ConcreteProductB"
# 工厂接口
class Factory:
def create_product(self):
pass
# 具体工厂类
class ConcreteFactoryA(Factory):
def create_product(self):
return ConcreteProductA()
class ConcreteFactoryB(Factory):
def create_product(self):
return ConcreteProductB()
# 客户端代码
if __name__ == "__main__":
factory_a = ConcreteFactoryA()
product_a = factory_a.create_product()
print(product_a.operation()) # 输出: Result of ConcreteProductA
factory_b = ConcreteFactoryB()
product_b = factory_b.create_product()
print(product_b.operation()) # 输出: Result of ConcreteProductB
- 产品接口:定义了一个产品接口
Product
,具体产品类ConcreteProductA
和ConcreteProductB
实现了该接口。 - 工厂接口:定义了一个工厂接口
Factory
,包含一个创建产品的方法create_product
。 - 具体工厂类:
ConcreteFactoryA
和ConcreteFactoryB
实现了工厂接口,负责创建具体产品。 - 客户端代码:在客户端代码中,使用具体工厂类创建产品对象,而不需要直接依赖具体的产品类。
工厂方法模式的一个重要优点是它允许用户在不修改现有代码的情况下引入新产品。这是通过以下方式实现的:
-
扩展工厂类:用户可以创建新的工厂类,继承自工厂接口,并实现
create_product
方法,以创建新的产品类型。 -
扩展产品类:用户可以创建新的产品类,继承自产品接口,并实现其方法。
-
使用多态:客户端代码可以使用工厂接口来创建产品,而不需要知道具体的产品类。这使得在引入新产品时,客户端代码不需要进行任何修改。
假设我们要引入一个新的产品 ConcreteProductC
和一个新的工厂 ConcreteFactoryC
。
# 新的具体产品类
class ConcreteProductC(Product):
def operation(self):
return "Result of ConcreteProductC"
# 新的具体工厂类
class ConcreteFactoryC(Factory):
def create_product(self):
return ConcreteProductC()
# 客户端代码
if __name__ == "__main__":
factory_a = ConcreteFactoryA()
product_a = factory_a.create_product()
print(product_a.operation()) # 输出: Result of ConcreteProductA
factory_b = ConcreteFactoryB()
product_b = factory_b.create_product()
print(product_b.operation()) # 输出: Result of ConcreteProductB
# 使用新的工厂和产品
factory_c = ConcreteFactoryC()
product_c = factory_c.create_product()
print(product_c.operation()) # 输出: Result of ConcreteProductC
- 新的具体产品类:
ConcreteProductC
实现了Product
接口,提供了自己的operation
方法。 - 新的具体工厂类:
ConcreteFactoryC
实现了Factory
接口,负责创建ConcreteProductC
实例。 - 客户端代码:在客户端代码中,创建了新的工厂
ConcreteFactoryC
,并使用它来创建新的产品ConcreteProductC
。客户端代码无需修改,依然使用工厂接口来创建产品。
1.1.3 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式通常用于需要创建多个相关对象的场景。
# 产品接口
class ProductA:
def operation_a(self):
pass
class ProductB:
def operation_b(self):
pass
# 具体产品类
class ConcreteProductA1(ProductA):
def operation_a(self):
return "Result of ConcreteProductA1"
class ConcreteProductA2(ProductA):
def operation_a(self):
return "Result of ConcreteProductA2"
class ConcreteProductB1(ProductB):
def operation_b(self):
return "Result of ConcreteProductB1"
class ConcreteProductB2(ProductB):
def operation_b(self):
return "Result of ConcreteProductB2"
# 抽象工厂接口
class AbstractFactory:
def create_product_a(self):
pass
def create_product_b(self):
pass
# 具体工厂类
class ConcreteFactory1(AbstractFactory):
def create_product_a(self):
return ConcreteProductA1()
def create_product_b(self):
return ConcreteProductB1()
class ConcreteFactory2(AbstractFactory):
def create_product_a(self):
return ConcreteProductA2()
def create_product_b(self):
return ConcreteProductB2()
# 客户端代码
if __name__ == "__main__":
factory1 = ConcreteFactory1()
product_a1 = factory1.create_product_a()
product_b1 = factory1.create_product_b()
print(product_a1.operation_a()) # 输出: Result of ConcreteProductA1
print(product_b1.operation_b()) # 输出: Result of ConcreteProductB1
factory2 = ConcreteFactory2()
product_a2 = factory2.create_product_a()
product_b2 = factory2.create_product_b()
print(product_a2.operation_a()) # 输出: Result of ConcreteProductA2
print(product_b2.operation_b()) # 输出: Result of ConcreteProductB2
- 产品接口:定义了两个产品接口
ProductA
和ProductB
,具体产品类实现了这些接口。 - 抽象工厂接口:定义了一个抽象工厂接口
AbstractFactory
,包含创建产品的方法。 - 具体工厂类:
ConcreteFactory1
和ConcreteFactory2
实现了抽象工厂接口,负责创建一系列相关的产品。 - 客户端代码:在客户端代码中,使用具体工厂类创建产品对象,而不需要直接依赖具体的产品类。
1.2 工厂模式的优点
- 解耦:客户端代码与具体的产品类解耦,客户端只需要依赖于工厂接口。
- 灵活性:可以在不修改客户端代码的情况下引入新的产品类。
- 易于扩展:可以通过添加新的工厂类和产品类来扩展系统。
1.3 工厂模式的应用场景
- 当一个类不知道它所必须创建的对象的类时。
- 当一个类希望通过子类来指定它所创建的对象时。
- 当需要将对象的创建与使用分离时。
2. 示例 1:工厂模式在图形绘制应用中的应用
# 图形接口
class Shape:
def draw(self):
pass
# 具体图形类
class Circle(Shape):
def __init__(self, color):
self.color = color
def draw(self):
return f"Drawing a {self.color} Circle"
class Rectangle(Shape):
def __init__(self, color):
self.color = color
def draw(self):
return f"Drawing a {self.color} Rectangle"
class Triangle(Shape):
def __init__(self, color):
self.color = color
def draw(self):
return f"Drawing a {self.color} Triangle"
class Square(Shape):
def __init__(self, color):
self.color = color
def draw(self):
return f"Drawing a {self.color} Square"
# 工厂类
class ShapeFactory:
@staticmethod
def create_shape(shape_type, color):
if shape_type == "Circle":
return Circle(color)
elif shape_type == "Rectangle":
return Rectangle(color)
elif shape_type == "Triangle":
return Triangle(color)
elif shape_type == "Square":
return Square(color)
else:
raise ValueError("Unknown shape type")
# 图形管理器
class ShapeManager:
def __init__(self):
self.shapes = []
def add_shape(self, shape):
self.shapes.append(shape)
def draw_all(self):
for shape in self.shapes:
print(shape.draw())
# 客户端代码
if __name__ == "__main__":
shape_manager = ShapeManager()
# 直接定义形状类型和颜色
shapes_to_create = [
("Circle", "Red"),
("Rectangle", "Blue"),
("Triangle", "Green"),
("Square", "Yellow")
]
for shape_type, color in shapes_to_create:
shape = ShapeFactory.create_shape(shape_type, color)
shape_manager.add_shape(shape)
# 绘制所有图形
shape_manager.draw_all()
Drawing a Red Circle
Drawing a Blue Rectangle
Drawing a Green Triangle
Drawing a Yellow Square
-
图形接口:定义了一个图形接口
Shape
,所有具体图形类(如Circle
、Rectangle
、Triangle
和Square
)都实现了该接口,并提供了draw
方法。 -
具体图形类:每个具体图形类都有一个构造函数,接受颜色参数,并实现了
draw
方法,返回绘制该图形的描述。 -
工厂类:
ShapeFactory
类提供了一个静态方法create_shape
,根据传入的形状类型和颜色创建不同类型的图形对象。这样,客户端代码只需调用工厂方法,而不需要直接依赖具体的图形类。 -
图形管理器:
ShapeManager
类用于管理所有创建的图形对象。它可以添加图形并绘制所有图形。 -
客户端代码:在客户端代码中,直接定义了一个形状和颜色的列表,使用工厂类创建相应的图形对象,并将它们添加到图形管理器中。最后,调用
draw_all
方法绘制所有图形。