《抽象工厂模式》|设计模式系列第04篇
系列:创建型模式 · 抽象工厂模式(Abstract Factory Pattern)
关键词:产品族、产品等级、抽象工厂、一套相关产品、工厂方法升级版
一、什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖产品的接口,而无需指定它们具体的类。

属于创建型设计模式。
区分工厂方法 vs 抽象工厂
- 工厂方法:一个工厂只生产一种产品(单一产品)
- 抽象工厂:一个工厂可以生产一组配套产品(产品族)
两个核心概念:
- 产品族:同一个工厂产出的一组配套产品。例如:小米工厂生产小米手机、小米耳机;华为工厂生产华为手机、华为耳机。
- 产品等级:同类产品的不同实现。手机是一个产品等级,耳机是另一个产品等级。
核心意图
保证客户端使用同一产品族的一套产品;隔离具体产品的创建,客户端只依赖抽象接口。新增产品族很方便,但新增产品等级非常麻烦。
适用场景
- 系统需要成套创建一组相关联的产品,保证配套使用
- 产品有多个系列,系统只需要使用其中某一个系列
- 希望客户端只使用抽象接口,屏蔽具体产品实现类
⚠️ 缺点预警:当产品族需要新增一类产品(新增产品等级),抽象工厂和所有具体工厂都要修改,违反开闭原则。
二、UML结构图
角色划分:
- AbstractFactory(抽象工厂):声明一组创建不同产品的方法
- ConcreteFactory(具体工厂):实现抽象工厂,生产对应产品族的全部产品
- AbstractProduct(抽象产品):每种产品的公共接口(多个抽象产品)
- ConcreteProduct(具体产品):抽象产品的具体实现,属于某个产品族

三、Java 完整示例
场景:电子产品工厂,可以生产手机 Phone 和耳机 Headphone。
产品族:小米产品族、华为产品族。
产品等级:手机、耳机。
1. 抽象产品
// 抽象产品:手机
public interface Phone {
void call();
}
// 抽象产品:耳机
public interface Headphone {
void listen();
}
2. 具体产品
// 小米手机
public class MiPhone implements Phone {
@Override
public void call() {
System.out.println("小米手机拨打电话");
}
}
// 小米耳机
public class MiHeadphone implements Headphone {
@Override
public void listen() {
System.out.println("小米耳机播放音频");
}
}
// 华为手机
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("华为手机拨打电话");
}
}
// 华为耳机
public class HuaweiHeadphone implements Headphone {
@Override
public void listen() {
System.out.println("华为耳机播放音频");
}
}
3. 抽象工厂
// 抽象工厂:电子产品工厂,可以生产手机+耳机一组产品
public interface ElectronicFactory {
Phone createPhone();
Headphone createHeadphone();
}
4. 具体工厂
// 小米工厂:小米产品族
public class MiFactory implements ElectronicFactory {
@Override
public Phone createPhone() {
return new MiPhone();
}
@Override
public Headphone createHeadphone() {
return new MiHeadphone();
}
}
// 华为工厂:华为产品族
public class HuaweiFactory implements ElectronicFactory {
@Override
public Phone createPhone() {
return new HuaweiPhone();
}
@Override
public Headphone createHeadphone() {
return new HuaweiHeadphone();
}
}
5. 客户端调用
public class Client {
public static void main(String[] args) {
// 切换工厂即可切换整套产品族
ElectronicFactory factory = new MiFactory();
Phone phone = factory.createPhone();
Headphone headphone = factory.createHeadphone();
phone.call();
headphone.listen();
System.out.println("=====切换华为产品族=====");
factory = new HuaweiFactory();
phone = factory.createPhone();
headphone = factory.createHeadphone();
phone.call();
headphone.listen();
}
}
客户端只依赖抽象 ElectronicFactory、Phone、Headphone,所有具体类隔离。
想要切换整套产品,只需要更换一行工厂实例代码。
四、优缺点总结
✅ 优点
- 保证同一产品族的产品配套使用
- 新增产品族简单,符合开闭原则
- 客户端与具体产品解耦,面向抽象编程
❌ 缺点
- 新增产品等级困难:例如要新增手表 Watch,抽象工厂接口要增加方法,所有工厂都要修改,破坏开闭原则
- 类数量多,结构复杂
五、工厂方法 vs 抽象工厂对比
| 模式 | 生产能力 | 扩展特点 |
|---|---|---|
| 工厂方法模式 | 一个工厂只生产一种产品 | 新增产品简单,类爆炸 |
| 抽象工厂模式 | 一个工厂生产一组配套产品 | 新增产品族简单;新增产品等级困难 |
六、框架源码应用
- JDK
java.sql:Connection、Statement 就是产品族;不同数据库驱动就是具体工厂 - Spring
BeanFactory部分子接口,类似抽象工厂思想
七、小结
抽象工厂核心:工厂可以生产一整套相关产品,用来约束产品族。
适合产品等级固定,产品族需要频繁扩展的场景。如果产品等级经常变动,不要使用抽象工厂。
0 条笔记