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