Skip to content

抽象工厂模式(Abstract Factory Pattern)

1. 官方定义

"Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)

核心:提供一个接口,用于创建一组相关或依赖的对象,而无需指定它们的具体类。

2. 模式解释

核心思想

  • 产品族(Product Family):一组相互关联或依赖的对象(例如 GUI 中的按钮、文本框、滚动条需风格统一)。
  • 抽象工厂:定义创建产品族的接口,具体工厂负责实现该接口以生成特定风格的产品。
  • 客户端解耦:客户端仅依赖抽象工厂和抽象产品接口,不感知具体实现。

典型结构

plaintext
                |<<Interface>>|
                AbstractFactory

                     | implements
                     |
      ┌──────────────┴──────────────┐
      |                             |
ConcreteFactoryA             ConcreteFactoryB
      |                             |
createProduct1() → ProductA1       createProduct1() → ProductB1
createProduct2() → ProductA2       createProduct2() → ProductB2

|<<Interface>>|            |<<Interface>>|
Product1                    Product2
   △                          △
   | implements               | implements
   |                          |
ProductA1 ──────────────── ProductA2
ProductB1 ──────────────── ProductB2

优点

  • 一致性保证:确保同一产品族中的对象协同工作(如 Windows 风格的所有组件)。
  • 开闭原则支持:新增产品族时只需扩展新工厂,无需修改已有代码。
  • 客户端简化:客户端代码仅依赖抽象接口,与具体实现解耦。

缺点

  • 扩展产品类型困难:新增产品类型(如新增一个 Product3)需修改所有工厂接口和实现类。
  • 复杂度高:需预先设计完善的产品族结构,否则易过度设计。

3. 解决的问题

经典场景

  1. 跨平台 UI 组件
    • 为 Windows、Mac、Linux 提供风格统一的按钮(Button)、文本框(TextBox)。
  2. 数据库访问抽象
    • 支持 MySQL、Oracle 等数据库的 ConnectionCommandAdapter 组件的兼容创建。
  3. 系统换肤功能
    • 切换主题时,确保所有 UI 元素(颜色、字体、图标)风格一致。

4. 实现注意事项

关键实现点

  1. 产品族定义
    • 明确哪些对象属于同一产品族(如 Button + TextBox 属于 UI 组件族)。
  2. 接口设计
    • 抽象工厂接口需声明所有产品类型的创建方法(如 createButton(), createTextBox())。
  3. 产品兼容性
    • 确保同一工厂创建的对象能协同工作(如 Windows 工厂生产的按钮不能与 Mac 文本框混用)。
  4. 配置管理
    • 通过配置文件、环境变量或依赖注入(如 Spring)动态选择具体工厂(如 WindowsFactory vs MacFactory)。

代码片段示例

java
// 抽象产品族
interface Button { void render(); }
interface TextBox { void input(); }

// 具体产品(Windows 风格)
class WindowsButton implements Button { /* ... */ }
class WindowsTextBox implements TextBox { /* ... */ }

// 抽象工厂
interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}

// 具体工厂(Windows)
class WindowsFactory implements GUIFactory {
    public Button createButton() { return new WindowsButton(); }
    public TextBox createTextBox() { return new WindowsTextBox(); }
}

5. 实现变体

两种常见实现方式

类型特点适用场景
标准抽象工厂每个产品族对应一个具体工厂类(如 WindowsFactoryMacFactory产品族类型固定且明确
动态工厂(参数化)通过参数选择产品族(如 createUIComponent("Windows")产品族类型由外部条件动态决定(需注意违反 OCP 的风险)

6. 相似模式对比

模式核心区别
工厂方法模式关注创建单一产品,而抽象工厂模式创建一组相关产品
建造者模式分步骤构建复杂对象,抽象工厂直接返回完整对象组
原型模式通过克隆生成对象,抽象工厂通过工厂方法生成对象

7. 组合使用场景

常见搭配模式

  1. 单例模式
    • 场景:确保具体工厂类全局唯一(如数据库工厂只需一个实例)。
    • 组合方式:将 ConcreteFactory 实现为单例。
  2. 原型模式
    • 场景:快速生成复杂产品族的副本(如游戏中的地图模板生成器)。
  3. 组合模式
    • 场景:统一处理产品族中的复杂结构(如 UI 容器中包含多个组件)。

8. 总结记忆点

  • 核心价值:为相关对象组提供统一创建的抽象层。
  • 一句话区分工厂方法 vs 抽象工厂
    • 工厂方法:1 个工厂 → 1 个产品
    • 抽象工厂:1 个工厂 → N 个关联产品
  • 适用性判断:当系统需要多维度切换产品组合时优先考虑(如同时切换操作系统和 UI 主题)。