简单工厂、工厂方法、抽象工厂 完整对比+业务场景
三者统称工厂家族模式,核心目标:封装对象创建逻辑,分离「创建」与「使用」,避免代码到处 new Xxx()。
递进关系:简单工厂(静态工厂)→ 工厂方法 → 抽象工厂,抽象程度、扩展性逐级提升。
一、逐个拆解定义、结构、代码、场景
1. 简单工厂模式(静态工厂 Static Factory)
核心定义
一个统一工厂类,内部通过判断逻辑(if/switch)根据传入参数,创建不同产品实例。
不属于GOF23种设计模式,但日常开发最常用。
角色
- 产品抽象 Product:所有产品统一接口
- 具体产品 ConcreteProductA/B:实现产品接口
- 工厂 Factory:唯一静态类,提供静态创建方法
create(type)
核心特点
- 只有一个工厂包揽所有产品创建;
- 新增产品必须修改工厂内部if判断,违反开闭原则;
- 静态方法创建,调用简单:
Factory.create("A")。
极简示例
// 产品接口
public interface Pay {
void pay(BigDecimal money);
}
// 具体产品
class Alipay implements Pay {
public void pay(BigDecimal money) { System.out.println("支付宝支付"); }
}
class WechatPay implements Pay {
public void pay(BigDecimal money) { System.out.println("微信支付"); }
}
// 唯一简单工厂
public class PayFactory {
// 静态创建方法
public static Pay createPay(String type) {
if ("alipay".equals(type)) {
return new Alipay();
} else if ("wechat".equals(type)) {
return new WechatPay();
}
throw new RuntimeException("渠道不存在");
}
}
// 使用
Pay pay = PayFactory.createPay("alipay");
pay.pay(new BigDecimal(100));
适用业务场景
- 产品类型少、几乎不新增(2~5种以内);
- 对象创建逻辑简单,没有复杂前置初始化;
- 工具类统一生产实例:
- 支付渠道少量固定(早期只有微信、支付宝)
- 文件解析器:txt、csv 少量格式
- 日志输出:控制台、文件两种输出
- 工具层快速封装,不想创建大量工厂类。
缺点
新增产品就要改工厂的if分支,代码臃肿,产品多后极难维护。
2. 工厂方法模式(Factory Method)
核心定义
一个产品对应一个独立工厂。
先抽象「工厂父类」和「产品父类」;每新增一个产品,配套新增一个产品工厂,各自负责自己产品的创建。
解决简单工厂违反开闭原则的问题。
角色
- 抽象产品 Product
- 具体产品 ProductA / ProductB
- 抽象工厂 Factory:定义创建产品标准方法
createProduct() - 具体工厂 FactoryA / FactoryB:各自重写创建对应产品
核心特点
- 工厂与产品一一对应;
- 新增产品:只新增产品类 + 对应工厂类,不修改原有代码,符合开闭;
- 缺点:类数量爆炸,产品越多,工厂类成倍增加。
承接上面支付示例改造为工厂方法
// 1. 产品接口不变 Pay
// 2. 抽象工厂
public interface PayFactory {
Pay createPay();
}
// 支付宝工厂
public class AlipayFactory implements PayFactory {
@Override
public Pay createPay() {
return new Alipay();
}
}
// 微信工厂
public class WechatPayFactory implements PayFactory {
@Override
public Pay createPay() {
return new WechatPay();
}
}
// 使用
PayFactory factory = new AlipayFactory();
Pay pay = factory.createPay();
pay.pay(new BigDecimal(100));
如果新增银联支付:只写 UnionPay + UnionPayFactory,原有代码完全不动。
适用业务场景
- 产品类型会频繁新增、迭代;
- 每个产品创建逻辑复杂(需要初始化参数、加载配置、建立连接);
- 各产品创建逻辑差异大,不适合塞在同一个工厂;
典型场景:
- 多种消息发送:短信、APP推送、站内信、邮件(后续持续新增渠道)
- 文件处理器:Excel、Word、PDF、PPT解析器
- 数据库驱动:MySQL、Oracle、SQLServer 连接工厂
- 报表生成器:PDF报表、Excel报表、Word报表
缺点
每加一个产品就要多一个工厂,类膨胀,代码冗余。
3. 抽象工厂模式(Abstract Factory)
核心定义
生产一族相关/配套产品的工厂。
工厂不再只生产单一产品,而是一次性产出一组相互依赖、配套使用的产品(产品族)。
关键词:产品族、产品等级。
举例子理解两个概念:
- 产品等级(同一类功能):支付 Pay、退款 Refund
- 产品族(同一厂商配套组件):支付宝族(Alipay + AliRefund)、微信族(WechatPay + WechatRefund)
抽象工厂同时提供createPay()、createRefund(),一个工厂产出整套配套能力。
角色
- 多个抽象产品:Pay(支付)、Refund(退款)
- 多组具体产品:Alipay/AliRefund、WechatPay/WechatRefund
- 抽象工厂 AbstractFactory:定义一族产品创建方法
- 具体工厂 AliFactory / WechatFactory:实现整套配套产品创建
代码示例
// 产品1:支付
public interface Pay { void pay(BigDecimal money); }
// 产品2:退款(同属一族配套)
public interface Refund { void refund(BigDecimal money); }
// 支付宝配套产品
class Alipay implements Pay{}
class AliRefund implements Refund{}
// 微信配套产品
class WechatPay implements Pay{}
class WechatRefund implements Refund{}
// 抽象工厂:同时生产支付、退款一组产品
public interface PayChannelFactory {
Pay createPay();
Refund createRefund();
}
// 支付宝整套工厂
public class AliFactory implements PayChannelFactory {
@Override public Pay createPay() { return new Alipay(); }
@Override public Refund createRefund() { return new AliRefund(); }
}
// 微信整套工厂
public class WechatFactory implements PayChannelFactory {
@Override public Pay createPay() { return new WechatPay(); }
@Override public Refund createRefund() { return new WechatRefund(); }
}
// 使用:同一厂商配套工具统一获取
PayChannelFactory factory = new AliFactory();
Pay pay = factory.createPay();
Refund refund = factory.createRefund();
核心特点
- 约束成套配套产品,保证同一族产品搭配使用(不会出现支付宝支付 + 微信退款这种混乱组合);
- 新增产品族(新增银联渠道):只新增一套工厂+产品,符合开闭;
- 致命缺点:新增产品等级(新增转账Transfer接口),必须修改顶层抽象工厂,所有实现工厂全部改动,违反开闭。
适用业务场景
系统有多套配套联动组件,成套切换:
- 支付渠道全套:支付、退款、查询账单、对账(一套工具绑定同一个渠道)
- 多端UI组件库:PC端按钮/弹窗、移动端按钮/弹窗(整套切换PC/移动端组件)
- 数据库全套操作:MySQL连接、MySQL事务、MySQL分页;Oracle全套对应组件
- 消息中间件套件:Rabbit生产者/消费者、Kafka生产者/消费者
- 多环境存储:阿里云OSS上传/删除、腾讯云COS上传/删除
- 多套报表引擎:A引擎导出+打印、B引擎导出+打印
缺点
如果需要新增产品功能(比如新增转账),顶层抽象工厂接口要加方法,所有实现工厂都要改,改动范围极大。
二、三者核心区别总表
| 对比维度 | 简单工厂(静态工厂) | 工厂方法 | 抽象工厂 |
|---|---|---|---|
| 工厂数量 | 仅一个全局工厂类 | 一个产品对应一个独立工厂 | 一个产品族对应一个工厂 |
| 生产能力 | 只生产一类产品 | 只生产一类产品 | 一次性生产一组配套产品 |
| 开闭原则 | ❌ 新增产品要改工厂if分支 | ✅ 新增产品只加类,不改旧代码 | ✅ 新增产品族兼容;❌ 新增产品等级全量改动 |
| 类数量 | 最少,结构简单 | 产品翻倍,类膨胀 | 产品+工厂数量最多,结构最重 |
| 核心解决 | 简单对象创建统一管理 | 解决简单工厂开闭问题 | 统一管理成套配套组件,约束产品组合 |
| 耦合度 | 高(工厂硬编码所有类型) | 低,产品完全解耦 | 族内解耦,跨等级耦合严重 |
一句话区分记忆
- 简单工厂:一个工厂造所有东西,产品少、不变动用;
- 工厂方法:一个产品一个工厂,单品频繁新增用;
- 抽象工厂:一套配套工具一组工厂,需要成套切换组件用。
三、选型决策流程(开发直接套用)
- 需求只有一类对象,种类固定很少、几乎不新增 → 简单工厂
- 只有一类对象,但后续会持续新增类型 → 工厂方法
- 需要同时创建多个配套、联动使用的一组对象,成套切换整套实现 → 抽象工厂
四、常见业务场景对比汇总
简单工厂场景
- 少量支付渠道(仅微信/支付宝,长期不新增)
- 简单文件解析(txt、csv)
- 简单日志输出(控制台/本地文件)
- 少量图片压缩算法
工厂方法场景
- 多类型消息推送(短信、邮件、APP、钉钉,持续加渠道)
- 多格式报表导出(Excel/PDF/Word/Markdown)
- 多种缓存实现(本地内存、Redis、Caffeine)
- 多种验证码生成(数字、字母、滑块验证)
抽象工厂场景
- 支付全套组件:支付、退款、对账、订单查询(按渠道成套)
- 云存储全套:上传、删除、预签名(阿里云/腾讯云两套)
- 多端UI组件:PC按钮弹窗 / 移动端按钮弹窗
- MQ套件:生产者、消费者、死信队列(Rabbit/Kafka两套)
- 数据库操作套件:连接、事务、分页、锁(MySQL/Oracle)
五、优缺点总结
简单工厂
优点:代码最少,上手简单,调用方便;
缺点:新增产品改if,违反开闭,产品多后难以维护。
工厂方法
优点:完全遵循开闭,单品扩展无侵入;
缺点:类数量暴增,大量工厂模板代码。
抽象工厂
优点:约束配套产品,保证组件成套匹配,统一切换整套实现;
缺点:扩展新功能(新产品接口)改动巨大,顶层接口需要全量修改。

2234

被折叠的 条评论
为什么被折叠?



