在上一篇中,我们用工厂方法模式 解决了"如何创建某一种对象"的问题。
但在真实项目中,你很快会遇到更复杂的情况:
不是创建一个对象,而是创建"一整套相关对象"。
这正是抽象工厂模式存在的原因。
一、什么时候工厂方法不够用
先看一个典型业务场景:
-
系统需要支持 多种支付渠道
-
每种支付渠道,都包含:
- 支付接口
- 对账接口
- 退款接口
也就是说:
对象之间存在"成组出现"的关系。
如果仍然使用工厂方法:
python
pay = PaymentFactory.create("wechat")
refund = RefundFactory.create("wechat")
recon = ReconciliationFactory.create("wechat")
问题来了:
- 调用方需要记住多组工厂
- 容易出现"混用产品族"的问题
- 结构开始变得混乱
二、抽象工厂模式是什么
**抽象工厂模式(Abstract Factory)**的定义:
提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。
核心关键词只有一个:
产品族(Product Family)
三、抽象工厂模式的结构
抽象工厂模式包含四个核心角色:
- 抽象产品 A
- 抽象产品 B
- 抽象工厂
- 具体工厂(对应一个产品族)
四、用支付系统举一个完整示例
1. 抽象产品
python
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
class Refund(ABC):
@abstractmethod
def refund(self, amount):
pass
2. 具体产品(微信产品族)
python
class WeChatPay(Payment):
def pay(self, amount):
print(f"微信支付 {amount}")
class WeChatRefund(Refund):
def refund(self, amount):
print(f"微信退款 {amount}")
3. 具体产品(支付宝产品族)
python
class AliPay(Payment):
def pay(self, amount):
print(f"支付宝支付 {amount}")
class AliRefund(Refund):
def refund(self, amount):
print(f"支付宝退款 {amount}")
4. 抽象工厂
python
class PayFactory(ABC):
@abstractmethod
def create_payment(self) -> Payment:
pass
@abstractmethod
def create_refund(self) -> Refund:
pass
5. 具体工厂
python
class WeChatFactory(PayFactory):
def create_payment(self) -> Payment:
return WeChatPay()
def create_refund(self) -> Refund:
return WeChatRefund()
class AliPayFactory(PayFactory):
def create_payment(self) -> Payment:
return AliPay()
def create_refund(self) -> Refund:
return AliRefund()
6. 使用方式
python
factory = WeChatFactory()
payment = factory.create_payment()
refund = factory.create_refund()
payment.pay(100)
refund.refund(50)
调用方只关心:
- 使用哪一个"产品族"
- 不关心具体类名
五、抽象工厂带来的好处
1. 保证产品族一致性
- 不会混用微信支付 + 支付宝退款
- 从结构上杜绝错误
2. 高度解耦
- 使用方只依赖抽象
- 完全不知道具体实现类
3. 易于切换产品族
python
factory = AliPayFactory()
一行代码切换整个系统的实现。
六、抽象工厂的代价
抽象工厂并不是"免费午餐"。
缺点:
- 类数量明显增加
- 结构复杂度上升
- 新增产品类型成本高
注意区别:
- 新增产品族(如新增"银联"):容易
- 新增产品类型(如新增"对账接口"):需要修改所有工厂
七、工厂方法 vs 抽象工厂
| 对比点 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建对象 | 单一对象 | 一组对象 |
| 产品关系 | 无强关联 | 同一产品族 |
| 复杂度 | 中 | 高 |
| 使用场景 | 对象类型多 | 产品族切换 |
八、Python 项目中的实际建议
在 Python 项目中:
- 小系统:工厂方法足够
- 中大型系统:产品族明确 → 抽象工厂
- 不要一上来就抽象工厂
- 让需求驱动设计,而不是反过来
九、总结
抽象工厂模式解决的是:
"如何成组地创建相互关联的对象"
它常用于:
- 跨平台实现
- 多渠道系统
- 插件化架构
- 大型框架底层设计