抽象工厂(Abstract Factory)是构建型设计模式中最能表现"系列对象成套创建能力"的模式。它不仅让你能够创建对象,还能确保这些对象"属于同一个产品族",从而在架构层面保持产品之间的一致性。
🌱 一、前言:为什么需要"成套创建对象"?
在实际业务中,常常需要让一组对象成套出现。例如:
- UI 系统中:同一主题下 Button、Checkbox、TextField 要保持一致的风格
- 数据库驱动中:连接器、命令、事务器需要属于同一厂商
- 跨平台应用:WindowsWidget、LinuxWidget、MacWidget 一定不能混用
如果仅仅用简单工厂或工厂方法,会导致对象之间风格可能"不统一"。
抽象工厂则以"产品族(Product Family)"为核心,确保成套生成。
🧱 二、抽象工厂模式的核心概念
抽象工厂主要包含以下角色:
- AbstractFactory(抽象工厂接口):定义一系列产品的创建方法
- ConcreteFactory(具体工厂):实现创建同一产品族的对象
- AbstractProduct(抽象产品):为产品定义统一接口
- ConcreteProduct(具体产品):产品族中真实的对象实现
最关键的点:
👉 抽象工厂不是创建一个对象,而是创建一整套对象。
🧩 三、用一个生活化示例理解:跨平台 UI 组件库
假设你正在开发一个 UI 库,需要支持:
- Light 主题
- Dark 主题
每个主题包含:
- Button
- Checkbox
- Dialog
不同主题下的控件必须成套出现,不能混搭。
🧭 四、类图:抽象工厂的结构
<<interface>> AbstractFactory +createButton() : Button +createCheckbox() : Checkbox LightFactory +createButton() +createCheckbox() DarkFactory +createButton() +createCheckbox() <<interface>> Button LightButton DarkButton <<interface>> Checkbox LightCheckbox DarkCheckbox
这是抽象工厂最标准的结构。
🔧 五、代码示例:以 Java 实现抽象工厂
1. 抽象产品
java
public interface Button {
void render();
}
public interface Checkbox {
void check();
}
2. 具体产品
java
public class LightButton implements Button {
public void render() { System.out.println("Light Button"); }
}
public class DarkButton implements Button {
public void render() { System.out.println("Dark Button"); }
}
public class LightCheckbox implements Checkbox {
public void check() { System.out.println("Light Checkbox"); }
}
public class DarkCheckbox implements Checkbox {
public void check() { System.out.println("Dark Checkbox"); }
}
3. 抽象工厂
java
public interface UIThemeFactory {
Button createButton();
Checkbox createCheckbox();
}
4. 具体工厂
java
public class LightThemeFactory implements UIThemeFactory {
public Button createButton() { return new LightButton(); }
public Checkbox createCheckbox() { return new LightCheckbox(); }
}
public class DarkThemeFactory implements UIThemeFactory {
public Button createButton() { return new DarkButton(); }
public Checkbox createCheckbox() { return new DarkCheckbox(); }
}
🚀 六、客户端如何选择具体工厂?
客户端只需决定使用哪个工厂:
java
public class Application {
private UIThemeFactory factory;
public Application(UIThemeFactory factory) {
this.factory = factory;
}
public void init() {
Button btn = factory.createButton();
Checkbox chk = factory.createCheckbox();
btn.render();
chk.check();
}
}
public class Main {
public static void main(String[] args) {
UIThemeFactory factory = new DarkThemeFactory();
Application app = new Application(factory);
app.init();
}
}
👉 只要替换工厂,就能成套更换所有 UI 风格。
🧭 七、抽象工厂模式的流程图
客户端决定使用哪种产品族 实例化具体工厂 通过工厂创建按钮/复选框等具体产品 客户端使用产品 产品族保持一致性
🎯 八、抽象工厂模式在架构中的价值
1. 保证产品族一致性
不会出现 LightButton + DarkCheckbox 的混搭情况。
2. 降低耦合
客户端只依赖抽象,不依赖具体实现。
3. 扩展性强
添加新主题只需新增一个具体工厂和具体产品类。
4. 隐藏复杂构建过程
客户端不关心产品如何创建,只关心工厂。
🔥 九、典型适用场景
- 跨平台 UI
- 数据库操作层(MySQL/Oracle/PostgreSQL)
- 游戏开发(武器、角色、装备成套生成)
- IoT 设备接口(不同厂商设备协议不同)
- Web 主题/皮肤切换
🆚 十、与工厂方法模式的差异对比
| 特性 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建对象数量 | 一个产品 | 一整套产品族 |
| 新增产品难度 | 较容易 | 需要修改所有工厂 |
| 产品族保证 | 无 | 强调一致性 |
| 结构复杂度 | 中 | 高 |
一句话总结:
工厂方法------创建单一产品,抽象工厂------成套创建产品族。
🛠️ 十一、抽象工厂的典型问题与缺点
尽管抽象工厂非常强大,也有一些不足:
- 新增产品(如 TextField)时,需要修改所有具体工厂,违反开闭原则
- 类数量激增:产品多、族多时,类会爆炸性增长
- 结构复杂:不适合小项目
🧪 十二、抽象工厂的常见变体与优化方式
1. 使用配置文件 + 反射自动选择工厂
java
String factoryClass = Config.get("ui.theme.factory");
UIThemeFactory factory = (UIThemeFactory) Class.forName(factoryClass).newInstance();
2. 使用 DI 容器管理工厂
如 Spring,让容器自动注入主题工厂。
3. 与建造者模式结合
更强的构建能力。
📦 十三、真实世界的使用案例
1. Java Swing UIManager
java
UIManager.setLookAndFeel(new NimbusLookAndFeel());
底层就是抽象工厂。
2. 数据库驱动 DriverManager
不同厂商实现同一接口。
3. 跨平台游戏引擎(Unity/Unreal)
多平台渲染器是一套产品族。
🧭 十四、总结:抽象工厂的设计精髓
抽象工厂最核心的价值在于:
👉 "让同一产品族的对象一起出现,并保持风格一致。"
它是构建型模式中解决"多产品族协作问题"的终极方案,让系统具有:
- 更高的一致性
- 更低的耦合
- 更强的可扩展性
如果你的系统需要在不同环境(平台、主题、厂商)之间切换,而每种环境下的组件是一整套,那么:
抽象工厂就是你最好的武器。