工厂方法是什么
工厂方法让子类或实现方决定实例化哪个具体类:调用方依赖创建接口而不是具体类型,新增产品时只扩展工厂实现。简单场景里,静态工厂方法(带名字的创建方法)与它效果等效,只是把创建逻辑收在一个方法中,顺便可以做校验与默认值填充。
基本信息
| 意图 | 把实例化推迟到实现方 |
|---|---|
| 参与者 | 产品接口、工厂、具体工厂 |
| 变体 | 静态工厂方法,用名字表达创建语义 |
| 收益 | 调用方不依赖具体类,替换实现不改调用点 |
| 相关模式 | 抽象工厂用于产品族场景 |
典型使用场景
- 同一接口有多个实现,按环境或配置选择
- 构造过程需要校验与默认值填充
- 需要给构造函数起更清楚的名字(按标识创建、按配置创建)
- 创建逻辑需要集中管理,避免散落各处
- 隔离第三方类型,把具体类限制在工厂内部
Java 示例
Java 示例
abstract class Dialog {
abstract Button createButton(); // 工厂方法,由子类决定具体产品
void render() { createButton().paint(); }
}
class WindowsDialog extends Dialog {
Button createButton() { return new WindowsButton(); }
}工厂的几种形态
| 形态 | 适用 | 注意 |
|---|---|---|
| 静态工厂方法 | 需要命名语义或封装校验 | 不要与构造语义混淆 |
| 工厂方法(继承) | 产品族按子类替换 | 子类数量会随产品增长 |
| 注册表工厂 | 实现按类型动态选择 | 装配点保持唯一 |
工厂的价值在于把具体类集中在一处:如果调用方仍在多处直接构造具体实现,工厂只是多包了一层方法,隔离并没有发生。
工厂里写业务分支,会让它逐渐变成什么都管的上帝类:创建之外的计算应该留在各自的实现或服务里。
创建往往伴随依赖:日志、时钟、限流器这些应显式传入工厂,而不是在里面临时创建,否则测试时无从替换,扩展实现也会互相牵连。