Java 抽象工厂模式(Abstract Factory Pattern)详解
🌟 什么是抽象工厂模式?
抽象工厂模式是工厂方法模式的升级版,提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。
🧠 使用场景
- 系统需要创建多个系列的产品对象
- 系统需要与多个产品系列中的一个进行交互
- 需要保证产品对象之间的兼容性(例如 UI 样式组件)
🏗️ 模式结构
- AbstractFactory(抽象工厂)
- ConcreteFactory(具体工厂)
- AbstractProduct(抽象产品)
- ConcreteProduct(具体产品)
- Client(客户端)
✅ 示例:跨平台 UI 工厂(Windows & Mac)
抽象产品接口
public interface Button {
void paint();
}
public interface TextField {
void render();
}
具体产品实现
public class WindowsButton implements Button {
public void paint() {
System.out.println("Rendering Windows Button");
}
}
public class MacButton implements Button {
public void paint() {
System.out.println("Rendering Mac Button");
}
}
public class WindowsTextField implements TextField {
public void render() {
System.out.println("Rendering Windows TextField");
}
}
public class MacTextField implements TextField {
public void render() {
System.out.println("Rendering Mac TextField");
}
}
抽象工厂接口
public interface GUIFactory {
Button createButton();
TextField createTextField();
}
具体工厂实现
public class WindowsFactory implements GUIFactory {
public Button createButton() {
return new WindowsButton();
}
public TextField createTextField() {
return new WindowsTextField();
}
}
public class MacFactory implements GUIFactory {
public Button createButton() {
return new MacButton();
}
public TextField createTextField() {
return new MacTextField();
}
}
客户端调用
public class Application {
private Button button;
private TextField textField;
public Application(GUIFactory factory) {
button = factory.createButton();
textField = factory.createTextField();
}
public void render() {
button.paint();
textField.render();
}
public static void main(String[] args) {
GUIFactory factory = new WindowsFactory(); // 可替换为 MacFactory
Application app = new Application(factory);
app.render();
}
}
🧩 优点
- 符合开闭原则,易于扩展新产品族
- 保证产品之间的兼容性
- 封装了对象的创建过程,客户端无需关心细节
⚠️ 缺点
- 每增加一个产品族都需要修改工厂接口,系统复杂度增加
- 不易支持“新产品等级结构”的变化
🆚 与工厂方法的区别
特点 | 工厂方法 | 抽象工厂 |
---|---|---|
创建对象数 | 一类产品 | 一族产品 |
类数量 | 工厂类较少 | 工厂类更多 |
产品间的关联 | 不强调关联 | 强调一族产品间的一致性 |
示例 | 创建单一 Logger | 创建一整套 UI 控件 |
✅ 使用建议
当产品对象有“系列”概念,且客户端必须使用同一产品族中的对象时,抽象工厂是最合适的选择。