一、说明
(一) 解决问题
提供了一种方式,在不指定具体类将要创建的情况下,将类的实例化操作延迟到子类中完成。可以实现客户端代码与具体类实现之间的解耦,使得系统更加灵活、可扩展和可维护。
(二) 使用场景
- 希望复用现有对象来节省系统资源, 而不是每次都重新创建对象时
- 如果无法预知对象确切类别及其依赖关系时
- 希望用户能扩展你软件库或框架的内部组件时
二、结构
- 产品 (Product) 将会对接口进行声明。 对于所有由创建者及其子类构建的对象, 这些接口都是通用的。
- 具体产品 (Concrete Products) 是产品接口的不同实现。
- 创建者 (Creator) 类声明返回产品对象的工厂方法。 该方法的返回对象类型必须与产品接口相匹配。你可以将工厂方法声明为抽象方法, 强制要求每个子类以不同方式实现该方法。 或者, 你也可以在基础工厂方法中返回默认产品类型。注意, 尽管它的名字是创建者, 但它最主要的职责并不是创建产品。 一般来说, 创建者类包含一些与产品相关的核心业务逻辑。 工厂方法将这些逻辑处理从具体产品类中分离出来。 打个比方, 大型软件开发公司拥有程序员培训部门。 但是, 这些公司的主要工作还是编写代码, 而非生产程序员。
- 具体创建者 (Concrete Creators) 将会重写基础工厂方法, 使其返回不同类型的产品。注意, 并不一定每次调用工厂方法都会创建新的实例。 工厂方法也可以返回缓存、 对象池或其他来源的已有对象。
三、伪代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__doc__ = """
工厂模式
将类的实例化操作延迟到子类中完成
例:通过传入不同的操作符,实现对两个数字的加减乘除运算
"""
from abc import ABC, abstractmethod
class Product(ABC):
"""
抽象基类
"""
num1 = None
num2 = None
@abstractmethod
def get_result(self):
pass
class ProductAdd(Product):
"""
具体产品类(加)
"""
def get_result(self):
return self.num1 + self.num2
class ProductSub(Product):
"""
具体产品类(减)
"""
def get_result(self):
return self.num1 - self.num2
class ProductMul(Product):
"""
具体产品类(乘)
"""
def get_result(self):
return self.num1 * self.num2
class ProductDiv(Product):
"""
具体产品类(除)
"""
def get_result(self):
return self.num1 / self.num2
class ProductErr(Product):
"""
具体产品类(错误)
"""
def get_result(self):
print("error")
return 0
class Factory:
"""
工厂类
"""
operation = {"+": ProductAdd(), "-": ProductSub(), "*": ProductMul(), "/": ProductDiv()}
def create_product(self, ch):
if ch in self.operation:
op = self.operation[ch]
else:
op = ProductErr()
return op
if __name__ == "__main__":
"""
num1: 1
num2: 2
ch: +
3.0
"""
num1 = float(input("num1: "))
num2 = float(input("num2: "))
ch = input("ch: ")
factory = Factory()
product = factory.create_product(ch)
product.num1 = num1
product.num2 = num2
print(product.get_result())
四、优缺点
优点
- 你可以避免创建者和具体产品之间的紧密耦合。
- 单一职责原则。你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
- 开闭原则。无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。
缺点
- 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。