抽象工厂模式(Abstract Factory Pattern)是创建型设计模式的一种,用于创建一组相关或相互依赖的对象,而无需指定它们的具体类。
抽象工厂模式通常用于创建多个相关的产品对象,而不希望依赖于具体的产品类。它允许客户端通过工厂接口获取一系列产品,而无需关心产品的具体实现。
一、定义
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
二、适用场景
- 系统中有多个产品族(产品组),每个产品族由多个相互关联的产品组成。
- 系统需要独立于这些产品的创建过程。
- 需要保证“产品族的一致性”。
三、结构:
抽象产品:定义产品的接口(或抽象类)。
具体产品:实现产品接口的具体类。
抽象工厂:声明创建抽象产品的方法。
具体工厂:实现抽象工厂中的方法,负责创建具体的产品对象。
四、结构图(UML)
┌────────────────────┐
│ AbstractFactory │<────────────────────────────┐
│ + createProductA() │ │
│ + createProductB() │ │
└────────────────────┘ │
▲ │
┌───────────────────────────┐ ┌────────────────────────────┐
│ ConcreteFactory1 │ │ ConcreteFactory2 │
│ + createProductA() → A1 │ │ + createProductA() → A2 │
│ + createProductB() → B1 │ │ + createProductB() → B2 │
└───────────────────────────┘ └────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ ProductA1 │ │ ProductB1 │ │ ProductA2 │ │ ProductB2 │
└────────────┘ └────────────┘ └────────────┘ └────────────┘
五、示例代码
需求:
假设我们有一个汽车制造厂,它生产不同类型的汽车(如:电动汽车和燃油汽车)。
每种类型的汽车包括多个组件,如 引擎、轮胎、座椅 等。
我们使用 抽象工厂模式 来定义汽车的各个组件,并通过工厂生产不同类型的汽车。
每种汽车类型对应一个工厂,它能制造一系列相关的汽车部件。
1. 抽象产品接口
/**
* 1. 抽象产品接口(Abstract Product)
*/
// 轮胎接口
public interface Tire {
void install();
}
/**
* 具体产品(Concrete Products)
*/
// 燃油轮胎
public class GasolineTire implements Tire {
@Override
public void install() {
System.out.println("安装燃油轮胎");
}
}
/**
* 1. 抽象产品接口(Abstract Product)
*/
// 座椅接口
public interface Seat {
void setup();
}
/**
* 1. 抽象产品接口(Abstract Product)
*/
// 引擎接口
public interface Engine {
void assemble();
}
2. 具体产品实现
/**
* 具体产品(Concrete Products)
*/
// 燃油轮胎
public class GasolineTire implements Tire {
@Override
public void install() {
System.out.println("安装燃油轮胎");
}
}
/**
* 具体产品(Concrete Products)
*/
// 燃油座椅
public class GasolineSeat implements Seat {
@Override
public void setup() {
System.out.println("安装燃油座椅");
}
}
/**
* 具体产品(Concrete Products)
*/
// 燃油引擎
public class GasolineEngine implements Engine {
@Override
public void assemble() {
System.out.println("组装燃油引擎");
}
}
4. 抽象工厂接口
/**
* 3. 抽象工厂接口(Abstract Factory)
*/
public interface CarFactory {
Engine createEngine();
Tire createTire();
Seat createSeat();
}
5. 具体工厂实现
/**
* 4. 具体工厂(Concrete Factories)
*/
// 燃油汽车工厂
public class GasolineCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new GasolineEngine();
}
@Override
public Tire createTire() {
return new GasolineTire();
}
@Override
public Seat createSeat() {
return new GasolineSeat();
}
}
/**
* 4. 具体工厂(Concrete Factories)
*/
// 电动汽车工厂
public class ElectricCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new ElectricEngine();
}
@Override
public Tire createTire() {
return new ElectricTire();
}
@Override
public Seat createSeat() {
return new ElectricSeat();
}
}
6. 客户端代码
public class Client {
public static void main(String[] args) {
// 创建电动汽车工厂
CarFactory electricFactory = new ElectricCarFactory();
Engine electricEngine = electricFactory.createEngine();
Tire electricTire = electricFactory.createTire();
Seat electricSeat = electricFactory.createSeat();
// 组装电动汽车
electricEngine.assemble(); // 输出: 组装电动引擎
electricTire.install(); // 输出: 安装电动轮胎
electricSeat.setup(); // 输出: 安装电动座椅
// 创建燃油汽车工厂
CarFactory gasolineFactory = new GasolineCarFactory();
Engine gasolineEngine = gasolineFactory.createEngine();
Tire gasolineTire = gasolineFactory.createTire();
Seat gasolineSeat = gasolineFactory.createSeat();
// 组装燃油汽车
gasolineEngine.assemble(); // 输出: 组装燃油引擎
gasolineTire.install(); // 输出: 安装燃油轮胎
gasolineSeat.setup(); // 输出: 安装燃油座椅
}
}
五、优缺点
✅ 优点
- 保持产品族内部的一致性(例如 Mac 风格组件不会混杂 Windows 风格)。
- 解耦客户端代码与具体产品类。
- 易于扩展整个产品族(只需新增工厂类和对应产品实现)。
❌ 缺点
- 难以扩展“新的产品种类”(即新增一个
Label
类),因为所有工厂都必须改动。 - 类文件数量增多,结构较复杂。
六、现实类比
- UI主题系统:一个“暗黑主题工厂”创建暗色按钮、暗色文本框;一个“浅色主题工厂”创建浅色控件。
- 数据库访问接口:一个工厂创建 MySQL 的连接对象、语句对象;另一个工厂创建 Oracle 的对应对象。
七、与其他模式的区别
模式 | 作用 |
简单工厂模式 | 用于创建一个对象,逻辑集中在一个工厂类中。 |
工厂方法模式 | 每种产品对应一个工厂类。 |
抽象工厂模式 | 用于创建多个产品,并保证这些产品属于同一个产品族。 |
八、总结一句话:
抽象工厂模式用于创建一组相互关联的对象,避免产品族之间混用,支持统一风格、平台的切换。