Skip to content

工厂方法模式(Factory Method Pattern)

1. 官方定义

"Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)

核心:定义一个创建对象的接口,但由子类决定具体实例化哪个类。工厂方法将对象创建延迟到子类。

2. 模式解释

核心思想

  • 解耦创建逻辑:将对象的创建与使用分离,调用者无需关心具体实现类。
  • 支持扩展:新增产品时只需扩展工厂子类,无需修改已有代码(符合开闭原则)。

典型结构

plaintext
                |<<Interface>>|
                Product

                   | implements
                   |
ConcreteProductA ──── ConcreteProductB
       △                     △
       |                     |
|<<Interface>>|        |<<Interface>>|
Creator                  ConcreteCreatorB

       |
ConcreteCreatorA

优点

  • 灵活性:支持动态切换产品类型(如配置文件驱动)。
  • 可维护性:创建逻辑集中管理,修改影响范围小。
  • 可扩展性:新增产品只需添加工厂子类,无需改动客户端。

缺点

  • 类膨胀:每个产品需对应一个工厂类,增加系统复杂度。
  • 过度设计风险:简单对象创建场景可能引入不必要的抽象。

3. 解决的问题

经典场景

  1. 对象创建依赖运行时条件
    • 示例:根据用户配置选择数据库类型(MySQL/Oracle)。
  2. 需要隔离具体类
    • 框架不希望暴露具体实现类(如 Spring 的 BeanFactory)。
  3. 实现跨平台兼容
    • 不同操作系统创建不同风格的 UI 组件(如按钮、窗口)。

4. 实现注意事项

关键实现点

  1. 工厂接口设计
    • 工厂方法通常声明为抽象方法(或接口方法),返回抽象产品类型。
  2. 产品层级一致性
    • 所有具体产品必须实现同一抽象接口或继承同一父类。
  3. 依赖注入支持
    • 可通过配置文件、注解等方式动态绑定工厂实现(如 Spring 的 @Bean)。
  4. 异常处理
    • 工厂方法需明确处理创建失败场景(如无效参数、资源不足)。

代码片段示例

java
// 抽象产品
interface Logger {
    void log(String message);
}

// 具体产品
class FileLogger implements Logger { /* 写入文件 */ }
class DatabaseLogger implements Logger { /* 写入数据库 */ }

// 抽象工厂
interface LoggerFactory {
    Logger createLogger();
}

// 具体工厂
class FileLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
        return new FileLogger();
    }
}

5. 实现变体

三种常见实现方式

类型特点适用场景
简单工厂一个工厂类通过条件分支创建不同产品(严格说不属于标准工厂方法模式)产品类型少且固定
标准工厂方法每个产品对应一个独立工厂类,通过子类实现创建逻辑需要灵活扩展新产品
参数化工厂方法工厂方法接收参数决定创建哪种产品(如 createLogger(type)产品类型由外部条件动态决定

6. 相似模式对比

模式核心区别
抽象工厂模式关注创建产品家族(一组相关产品),而工厂方法模式创建单一产品
建造者模式分步骤构建复杂对象,而工厂方法直接返回完整对象
策略模式行为模式,用于算法选择;工厂方法属于创建型模式

7. 组合使用场景

常见搭配模式

  1. 抽象工厂模式
    • 场景:需要创建多个关联产品(如 GUI 中的按钮 + 文本框组合)。
    • 组合方式:每个产品族使用独立的工厂方法实现。
  2. 单例模式
    • 场景:工厂类本身需要全局唯一(如数据库连接池工厂)。
  3. 原型模式
    • 场景:通过克隆已有对象创建新实例(如游戏中的敌人生成器)。

8. 总结记忆点

  • 核心价值:通过子类化实现对象创建的延迟绑定。
  • 一句话区分工厂方法 vs 抽象工厂
    • 工厂方法:1 个工厂 → 1 个产品
    • 抽象工厂:1 个工厂 → N 个关联产品
  • 适用性判断:当系统中存在频繁新增产品类型的需求时优先考虑。