工厂方法模式(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 结构
  • 用最简单的方式解决创建问题
相关推荐
Li emily1 小时前
解决了加密货币api多币种订阅时的数据乱序问题
人工智能·python·api·fastapi
Dicky-_-zhang1 小时前
消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进
java·jvm
晨曦中的暮雨1 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
2301_781571421 小时前
Golang格式化输出占位符都有什么_Golang fmt占位符教程【通俗】
jvm·数据库·python
fake_ss1982 小时前
AI时代学习全栈项目开发的新范式
java·人工智能·学习·架构·个人开发·学习方法
asdzx672 小时前
使用 Python 为 PDF 添加页码 (详细教程)
python·pdf·页码
茉莉玫瑰花茶2 小时前
工作流的常见模式 [ 1 ]
java·服务器·前端
AI技术控2 小时前
《Transformers are Inherently Succinct》论文解读:从“能表达什么”到“多紧凑地表达”
人工智能·python·深度学习·机器学习·自然语言处理
未若君雅裁2 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
No8g攻城狮3 小时前
【人大金仓】wsl2+ubuntu22.04安装人大金仓数据库V9
java·数据库·spring boot·非关系型数据库