设计模式之抽象工厂模式 (Abstract Factory Pattern)
摘要: 抽象工厂模式核心解决产品族一致性问题,确保一组相关产品(如UI组件)风格统一。与工厂方法不同,它通过类型系统强制约束,使同一工厂创建的所有产品必然兼容。典型应用如跨平台UI框架(Qt/Flutter)保持组件风格一致。其优势在于客户端与具体类解耦、风格切换灵活,但代价是扩展新产品需修改所有工厂实现。本质是将**"产品族创建契约"编码到接口**中,避免混搭风险。适用场景:
📋 Research Summary
抽象工厂模式处理的是"产品族"的创建问题。在实际应用中,UI 框架(如 Qt、Flutter)使用此模式确保跨平台组件风格一致。与工厂方法关注"单个产品"不同,抽象工厂关注"一组相关产品"的协调创建。
🌱 逻辑原点
如果你的客厅买了现代风格的沙发,但餐厅却摆了维多利亚风格的椅子,这种混搭的混乱如何避免?
单个产品创建与产品族一致性的矛盾:每个组件单独创建时都是合法的,但组合在一起却风格冲突。
🧠 苏格拉底式对话
1️⃣ 现状:最原始的解法是什么?
为每个产品单独使用工厂方法:
class ModernUIFactory:
def create_button(self): return ModernButton()
def create_sofa(self): return ModernSofa()
class VictorianUIFactory:
def create_button(self): return VictorianButton()
def create_sofa(self): return VictorianSofa()
# 客户端
button = factory.create_button()
sofa = factory.create_sofa() # 如果这里不小心用错工厂...
优点:每个产品都有独立的创建逻辑。
问题:客户端仍然需要分别调用多个工厂方法,可能混用不同风格的工厂。
2️⃣ 瓶颈:规模扩大 100 倍时会在哪里崩溃?
当产品族扩展到 10 个产品(按钮、沙发、桌子、灯具、地毯…),且有 5 种风格(现代、维多利亚、装饰艺术、极简、工业)时:
- 组合爆炸:客户端代码需要知道 50 个具体类的存在
- 风格不一致风险:A 模块用现代工厂创建按钮,B 模块用维多利亚工厂创建沙发
- 约束难以强制:语言层面无法阻止混用不同风格的产品
核心矛盾:我们需要"风格一致性"这个跨产品的约束,但单个工厂方法无法表达这种关联。
3️⃣ 突破:必须引入什么新维度?
将产品族作为一等公民。
不是"分别创建各个产品",而是"创建一个完整的产品族"。工厂不再是一个方法,而是一个接口,定义了创建整个产品族的所有方法:
抽象工厂:我承诺能创建按钮、沙发、桌子
现代工厂:我的按钮是 ModernButton,沙发是 ModernSofa...
维多利亚工厂:我的按钮是 VictorianButton,沙发是 VictorianSofa...
这就是抽象工厂的本质:将"产品族一致性"作为创建契约的一部分。
📊 视觉骨架
关键洞察:抽象工厂的价值不在于"创建",而在于"约束"。它用类型系统强制保证了:从一个工厂创建的所有产品必然是同一风格。
⚖️ 权衡模型
公式:
Abstract Factory = 解决了产品族一致性 + 牺牲了新产品的扩展性 + 增加了接口的复杂度
代价分析:
- ✅ 解决: 产品族风格一致性、客户端与具体类完全解耦、切换风格只需换一个工厂
- ❌ 牺牲: 新增产品类型困难(需要修改所有工厂实现)、接口稳定性要求高
- ⚠️ 增加: 接口复杂度(工厂接口随产品类型增长)、理解成本(需要理解产品族概念)
使用建议:当系统需要支持多套"风格"或"主题",且每套风格包含多个相互关联的组件时使用。不要为单个产品使用抽象工厂。
🔁 记忆锚点
from abc import ABC, abstractmethod
class UIFactory(ABC):
"""
抽象工厂的本质:产品族的创建契约
"""
@abstractmethod
def create_button(self) -> "Button":
"""同一工厂创建的按钮和沙发风格必然一致"""
pass
@abstractmethod
def create_sofa(self) -> "Sofa":
pass
def client_code(factory: UIFactory) -> None:
"""
客户端完全不知道具体风格,但风格一致性由类型系统保证
"""
button = factory.create_button() # 现代 or 维多利亚?不知道,也不关心
sofa = factory.create_sofa() # 必然与 button 同风格
button.render()
sofa.lay_on()
一句话本质: 抽象工厂模式 = 将"产品族一致性"编码到类型系统中。
更多推荐



所有评论(0)