文章目录
-
- 前言
- [1. 工厂方法模式是什么?](#1. 工厂方法模式是什么?)
- [2. 它解决什么问题?](#2. 它解决什么问题?)
- [3. 核心结构](#3. 核心结构)
- [4. 示例](#4. 示例)
-
- [4.1 抽象产品:支付接口](#4.1 抽象产品:支付接口)
- [4.2 具体产品:AliPay、WeChatPay](#4.2 具体产品:AliPay、WeChatPay)
- [4.3 抽象创建者:定义工厂方法](#4.3 抽象创建者:定义工厂方法)
- [4.4 具体创建者:决定创建哪种产品](#4.4 具体创建者:决定创建哪种产品)
- [4.5 使用方:只依赖抽象创建者](#4.5 使用方:只依赖抽象创建者)
- [5. "工厂 + 延迟决策"](#5. “工厂 + 延迟决策”)
- [6. 优缺点](#6. 优缺点)
- [7. 适用场景总结](#7. 适用场景总结)
- [8. 与"简单工厂 / 抽象工厂"的区别](#8. 与“简单工厂 / 抽象工厂”的区别)
-
- [8.1 简单工厂(Simple Factory)](#8.1 简单工厂(Simple Factory))
- [8.2 工厂方法(Factory Method)](#8.2 工厂方法(Factory Method))
- [8.3 抽象工厂(Abstract Factory)](#8.3 抽象工厂(Abstract Factory))
- [9. 总结](#9. 总结)
前言
在 工厂方法模式(Factory Method)"里,我们关注的核心不是"怎么创建对象",而是:
把"对象的创建"延迟到子类去决定,从而让创建逻辑和使用逻辑解耦。
当你发现代码里到处是 new XXX()(而且具体实现会不断增加),就应该考虑用工厂方法模式把这种变化"隔离"起来。

1. 工厂方法模式是什么?
工厂方法模式 :定义一个创建对象的接口/抽象方法,但由子类决定要实例化哪一个类 。
也就是说:父类负责"定义创建过程",子类负责"决定创建哪个产品"。
2. 它解决什么问题?
你可能写出了这种"违背开闭原则"的代码:
java
public class PaymentService {
public void pay(String channel) {
if ("ALI".equals(channel)) {
new AliPay().pay();
} else if ("WECHAT".equals(channel)) {
new WeChatPay().pay();
}
}
}
当未来新增"银联支付""Apple Pay"等,你就得不停改 PaymentService。
这会导致:
- 扩展需要修改已有核心代码
- 创建逻辑混杂在业务逻辑里
- 可维护性下降
工厂方法模式的目标就是:
- 业务方只关心"通过工厂创建产品并调用"
- 新增产品时,只需要新增子类/工厂对应实现,尽量不改原有代码
3. 核心结构
工厂方法模式通常包含这几块:
- 抽象产品(Product):产品的公共接口/抽象类
- 具体产品(ConcreteProduct):产品实现类
- 抽象创建者(Creator) :声明工厂方法
factoryMethod() - 具体创建者(ConcreteCreator) :实现
factoryMethod(),决定创建哪个具体产品
用一句话串起来:
Creator 里有"创建产品"的方法声明,但真正
new哪个产品由子类来决定。
4. 示例
下面用"支付方式选择"来演示
4.1 抽象产品:支付接口
java
public interface Pay {
void pay();
}
4.2 具体产品:AliPay、WeChatPay
java
public class AliPay implements Pay {
@Override
public void pay() {
System.out.println("AliPay paying...");
}
}
public class WeChatPay implements Pay {
@Override
public void pay() {
System.out.println("WeChatPay paying...");
}
}
4.3 抽象创建者:定义工厂方法
java
public abstract class PayCreator {
// 工厂方法:由子类决定创建哪个具体产品
protected abstract Pay factoryMethod();
// 业务方法:父类固定流程,复用这套创建+调用逻辑
public void processPay() {
Pay pay = factoryMethod();
pay.pay();
}
}
4.4 具体创建者:决定创建哪种产品
java
public class AliPayCreator extends PayCreator {
@Override
protected Pay factoryMethod() {
return new AliPay();
}
}
public class WeChatPayCreator extends PayCreator {
@Override
protected Pay factoryMethod() {
return new WeChatPay();
}
}
4.5 使用方:只依赖抽象创建者
java
public class Main {
public static void main(String[] args) {
PayCreator creator = new AliPayCreator();
creator.processPay();
}
}
5. "工厂 + 延迟决策"
你可能注意到:
- 业务流程
processPay()放在抽象创建者里固定了 - "到底 new 哪个产品"交给子类实现
factoryMethod()
所以它是典型的:
- 把"创建变化点"抽象出来
- 把"使用固定流程"保留下来
6. 优缺点
优点
- 符合开闭原则
- 新增产品:新增"具体产品 + 对应具体创建者"
- 尽量不改动原有业务类
- 创建逻辑解耦
processPay()不关心具体new AliPay()还是new WeChatPay()
- 更易扩展
- 当产品族不断增长,代码结构更清晰
缺点
- 类会变多
- 每一种产品通常要对应一个具体创建者(也就是更多类)
- 如果只是简单 switch/if
- 工厂方法的引入可能有"过度设计"风险
7. 适用场景总结
建议在以下情况使用:
- 系统需要创建的对象类型不断增加
- 创建逻辑需要与业务逻辑解耦
- 希望"扩展一个产品"时,不要动核心业务流程
- 希望将
new操作从业务代码中抽离出来
8. 与"简单工厂 / 抽象工厂"的区别
8.1 简单工厂(Simple Factory)
- 通常只有一个工厂类,根据参数
switch/if返回不同产品 - 缺点:工厂类会膨胀,新增类型需要改工厂类
8.2 工厂方法(Factory Method)
- 每个"产品类型"对应自己的"创建者子类"
- 新增产品:新增子类,不一定改已有创建者(更符合开闭)
8.3 抽象工厂(Abstract Factory)
- 工厂方法解决的是:创建一个产品层级
- 抽象工厂解决的是:创建一整套产品族(多个相关产品要一起创建,并保持兼容性)
- 例如:不同 UI 主题(按钮/输入框/菜单)要成套创建
一句话区分:
- 工厂方法:一个产品维度的创建延迟
- 抽象工厂:多个产品维度的成套创建保证一致
9. 总结
工厂方法模式通过"抽象创建者 + 延迟到子类决定具体产品",把创建变化和使用逻辑解耦,从而更容易扩展、更符合开闭原则。