工厂方法模式(Factory Method)

在真实项目中,对象的创建往往比使用更复杂 。

如果你发现代码中频繁出现 if-else 或根据参数去 new 不同的类,那基本已经到了该用工厂方法模式的时候了。


一、工厂方法模式解决什么问题

先看一个非常常见的写法:

python 复制代码
def create_payment(pay_type):
    if pay_type == "wechat":
        return WeChatPay()
    elif pay_type == "alipay":
        return AliPay()
    elif pay_type == "bank":
        return BankPay()
    else:
        raise ValueError("unsupported pay type")

问题很明显:

  • 新增一种支付方式,必须修改这个函数
  • 创建逻辑与业务逻辑耦合
  • 违反开闭原则

工厂方法模式的目的就是:

把"创建对象的逻辑"从使用对象的地方解耦出来。


二、什么是工厂方法模式

**工厂方法模式(Factory Method)**的定义:

定义一个创建对象的接口,让子类决定实例化哪一个类。

核心思想:

  • 使用方只依赖抽象
  • 创建细节由工厂或子类负责

三、一个最基础的 Python 工厂方法示例

1. 抽象产品

python 复制代码
from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

2. 具体产品

python 复制代码
class WeChatPay(Payment):
    def pay(self, amount):
        print(f"微信支付 {amount}")

class AliPay(Payment):
    def pay(self, amount):
        print(f"支付宝支付 {amount}")

3. 工厂类

python 复制代码
class PaymentFactory:
    @staticmethod
    def create(pay_type: str) -> Payment:
        if pay_type == "wechat":
            return WeChatPay()
        if pay_type == "alipay":
            return AliPay()
        raise ValueError("unsupported pay type")

使用方:

python 复制代码
payment = PaymentFactory.create("wechat")
payment.pay(100)

四、为什么这还不够"工厂方法"

上面的写法虽然集中管理了创建逻辑,但:

  • 依然需要修改工厂代码
  • 本质还是 if-else

真正的工厂方法强调:

通过继承扩展工厂,而不是修改工厂。


五、标准工厂方法模式结构

1. 抽象工厂

python 复制代码
class PaymentFactory(ABC):
    @abstractmethod
    def create(self) -> Payment:
        pass

2. 具体工厂

python 复制代码
class WeChatPayFactory(PaymentFactory):
    def create(self) -> Payment:
        return WeChatPay()

class AliPayFactory(PaymentFactory):
    def create(self) -> Payment:
        return AliPay()

使用方式:

python 复制代码
factory = WeChatPayFactory()
payment = factory.create()
payment.pay(100)

新增支付方式时:

  • 新增产品类
  • 新增工厂类
  • 无需修改原有代码

六、Python 风格的工厂方法(推荐)

Python 中,很多时候没必要写那么多类。

使用字典 + 类引用

python 复制代码
class PaymentFactory:
    _mapping = {
        "wechat": WeChatPay,
        "alipay": AliPay,
    }

    @classmethod
    def create(cls, pay_type: str) -> Payment:
        try:
            return cls._mapping[pay_type]()
        except KeyError:
            raise ValueError("unsupported pay type")

优点:

  • 代码简洁
  • 易于维护
  • 更符合 Python 风格

七、工厂方法 vs 直接实例化

对比点 直接 new 工厂方法
扩展性 差 好
解耦 低 高
可测试性 差 好
代码复杂度 低 中

适用原则:

  • 对象类型固定、变化少 → 直接实例化
  • 对象类型多、变化频繁 → 工厂方法

八、工厂方法常见误区

1. 工厂类变成"上帝类"

  • 包含大量 if-else
  • 违反单一职责

解决方案:

  • 拆分工厂
  • 或引入抽象工厂

2. 为了工厂而工厂

  • 只有一个实现类
  • 没有扩展需求

👉 直接实例化即可。


九、总结

工厂方法模式的核心价值在于:

  • 解耦创建与使用
  • 遵循开闭原则
  • 为系统预留扩展空间

在 Python 中:

  • 思想比形式重要
  • 不必拘泥 UML 结构
  • 用最简单的方式解决创建问题
相关推荐
imgsq28 分钟前
电子学会考级 vs CCF-GESP:两套少儿编程考级怎么选
python·青少年编程
Smoothcloud润云1 小时前
PyTorch推理服务动态批处理实战:兼顾吞吐与延迟
人工智能·pytorch·python·深度学习·ai·gpu算力
蜗牛互联网1 小时前
GPT-6 与 Intelligent UI:从回答到可审计操作的产品迁移
java·人工智能·后端
码爸1 小时前
决策树介绍与示例
python·算法·机器学习
拂拉氏1 小时前
【知识讲解】 Linux之动静态库的了解
linux·运维·服务器·动静态库
临床数据科学和人工智能兴趣组1 小时前
正则表达式的基础语法的基本符号
开发语言·人工智能·python·正则表达式·r语言·r语言-4.2.1·workbudyy
王中阳Go1 小时前
Go 后端转 AI:非科班怎么补?一张 3 列路线表(可保存)
开发语言·人工智能·后端·python·golang·大语言模型
SL_staff2 小时前
运维救火实录:钉钉考勤API变更引发工资计算异常,我们用JVS-Logic可视化逻辑引擎实现分钟级热修复
java·mysql·全栈
Fcy6482 小时前
Linux下 五种IO模型的认识与⾮阻塞IO的实现
linux·服务器·io
SunnyDays10112 小时前
Java 查找并高亮 Word 文字:精确查找及正则表达式模糊查找
java·查找文字·word 文档·高亮文字·正则匹配查找·模糊查找