抽象工厂模式 (Abstract Factory Pattern)
什么是抽象工厂模式?
抽象工厂模式是一种创建型设计模式,它提供一个接口,用于创建相关或依赖对象族,而无需指定它们具体的类。
简单来说:抽象工厂模式就是创建一系列相关的对象,而不是单个对象。
生活中的例子
想象一家家具制造厂:
- 产品族:现代风格家具、古典风格家具
- 产品等级:椅子、沙发、桌子
| 风格 | 椅子 | 沙发 | 桌子 |
|---|---|---|---|
| 现代风格 | 现代椅子 | 现代沙发 | 现代桌子 |
| 古典风格 | 古典椅子 | 古典沙发 | 古典桌子 |
抽象工厂模式可以确保:
- 现代风格的椅子、沙发、桌子搭配在一起
- 古典风格的椅子、沙发、桌子搭配在一起
- 不会出现现代椅子配古典沙发的情况
为什么需要抽象工厂模式?
工厂方法模式的局限
工厂方法模式只能创建一种类型 的产品。如果需要创建多个相关产品,就需要多个工厂,这样会导致:
- 工厂类数量爆炸:每种产品都需要一个工厂
- 产品族无法保证一致性:可能创建出不匹配的产品组合
抽象工厂模式的优势
- 产品族一致性:确保创建的产品属于同一个产品族
- 代码解耦:客户端不需要知道具体创建的是哪个产品族
- 易于扩展:新增产品族时,只需新增对应的工厂类
抽象工厂模式的结构
┌─────────────────────────┐
│ AbstractFactory │ 抽象工厂
├─────────────────────────┤
│ + createProductA(): A │
│ + createProductB(): B │
│ + createProductC(): C │
└──────────┬──────────────┘
│ 继承
├──┬──────────────────┬──────────────┐
│ │ │
┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐
│ ConcreteFactory1 │ │ ConcreteFactory2 │ │ ... │ 具体工厂
└─────────────────────┘ └───────────────────┘ └────────────┘
┌─────────────────────────┐
│ AbstractProductA │ 抽象产品A
├─────────────────────────┤
│ + operation(): void │
└──────────┬──────────────┘
│ 继承
├──┬──────────────────┬──────────────┐
│ │ │
┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐
│ ProductA1 │ │ ProductA2 │ │ ... │ 具体产品A
└─────────────────────┘ └───────────────────┘ └────────────┘
┌─────────────────────────┐
│ AbstractProductB │ 抽象产品B
├─────────────────────────┤
│ + operation(): void │
└──────────┬──────────────┘
│ 继承
├──┬──────────────────┬──────────────┐
│ │ │
┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐
│ ProductB1 │ │ ProductB2 │ │ ... │ 具体产品B
└─────────────────────┘ └───────────────────┘ └────────────┘
代码示例
1. 定义抽象产品
java
// 抽象产品:形状接口
public interface Shape {
/**
* 绘制形状
*/
void draw();
}
// 抽象产品:颜色接口
public interface Color {
/**
* 填充颜色
*/
void fill();
}
2. 定义具体产品
java
// 具体产品:圆形
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 具体产品:矩形
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 具体产品:正方形
public class Square implements Shape {
@Override
public void draw() {
System.out.println("绘制正方形");
}
}
// 具体产品:红色
public class Red implements Color {
@Override
public void fill() {
System.out.println("填充红色");
}
}
// 具体产品:绿色
public class Green implements Color {
@Override
public void fill() {
System.out.println("填充绿色");
}
}
// 具体产品:蓝色
public class Blue implements Color {
@Override
public void fill() {
System.out.println("填充蓝色");
}
}
3. 定义抽象工厂
java
/**
* 抽象工厂:形状和颜色工厂
* 定义了创建形状和颜色的抽象方法
*/
public interface AbstractFactory {
/**
* 创建形状
* @param shapeType 形状类型
* @return 形状实例
*/
Shape getShape(String shapeType);
/**
* 创建颜色
* @param colorType 颜色类型
* @return 颜色实例
*/
Color getColor(String colorType);
}
4. 定义具体工厂
java
/**
* 具体工厂:形状工厂
* 负责创建各种形状
*/
public class ShapeFactory implements AbstractFactory {
@Override
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
} else if (shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
}
return null;
}
@Override
public Color getColor(String colorType) {
// 形状工厂不负责创建颜色
return null;
}
}
/**
* 具体工厂:颜色工厂
* 负责创建各种颜色
*/
public class ColorFactory implements AbstractFactory {
@Override
public Shape getShape(String shapeType) {
// 颜色工厂不负责创建形状
return null;
}
@Override
public Color getColor(String colorType) {
if (colorType == null) {
return null;
}
if (colorType.equalsIgnoreCase("RED")) {
return new Red();
} else if (colorType.equalsIgnoreCase("GREEN")) {
return new Green();
} else if (colorType.equalsIgnoreCase("BLUE")) {
return new Blue();
}
return null;
}
}
5. 定义工厂生产者
java
/**
* 工厂生产者:工厂创建器
* 根据传入的类型返回相应的工厂
*/
public class FactoryProducer {
/**
* 获取工厂
* @param choice 工厂类型
* @return 工厂实例
*/
public static AbstractFactory getFactory(String choice) {
if (choice.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
} else if (choice.equalsIgnoreCase("COLOR")) {
return new ColorFactory();
}
return null;
}
}
6. 使用工厂
java
/**
* 抽象工厂模式演示类
* 演示如何使用抽象工厂模式创建形状和颜色
*/
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
System.out.println("=== 抽象工厂模式演示 - 形状和颜色 ===\n");
// 获取形状工厂
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
// 获取颜色工厂
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
// 创建形状
System.out.println("--- 绘制形状 ---");
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
Shape shape2 = shapeFactory.getShape("RECTANGLE");
shape2.draw();
Shape shape3 = shapeFactory.getShape("SQUARE");
shape3.draw();
// 创建颜色
System.out.println("\n--- 填充颜色 ---");
Color color1 = colorFactory.getColor("RED");
color1.fill();
Color color2 = colorFactory.getColor("GREEN");
color2.fill();
Color color3 = colorFactory.getColor("BLUE");
color3.fill();
System.out.println("\n=== 抽象工厂模式的优势 ===");
System.out.println("1. 产品族一致性:可以创建相关的对象族");
System.out.println("2. 代码解耦:客户端不需要知道具体创建的是哪个产品");
System.out.println("3. 易于扩展:新增产品族时,只需新增对应的工厂类");
System.out.println("\n=== 实际应用场景 ===");
System.out.println("1. UI组件库:不同风格的按钮、文本框、菜单");
System.out.println("2. 数据库访问:不同数据库的连接、命令、参数");
System.out.println("3. 游戏开发:不同风格的道具、角色、场景");
System.out.println("4. 配置管理:不同环境的配置对象");
System.out.println("\n=== 与工厂方法的区别 ===");
System.out.println("工厂方法:创建单个对象");
System.out.println("抽象工厂:创建对象族(多个相关对象)");
System.out.println("\n=== 扩展性说明 ===");
System.out.println("新增形状:只需在ShapeFactory中添加新的形状类");
System.out.println("新增颜色:只需在ColorFactory中添加新的颜色类");
System.out.println("新增产品族:需要修改AbstractFactory接口和所有工厂类");
}
}
抽象工厂模式的优点
- 产品族一致性:确保创建的产品属于同一个产品族
- 代码解耦:客户端与具体产品解耦
- 易于扩展:新增产品族时,只需新增对应的工厂类
- 符合开闭原则:对扩展开放,对修改关闭
抽象工厂模式的缺点
- 扩展困难:新增产品等级(新增产品类型)需要修改所有工厂类
- 类数量爆炸:每增加一个产品族,就需要增加多个产品类
- 系统复杂度增加:引入了多个抽象层,增加了系统的理解难度
适用场景
- 需要创建产品族:需要创建一系列相关的对象
- 产品族需要一致性:确保创建的产品属于同一个产品族
- 系统独立于产品的创建:客户端不依赖具体产品的创建细节
- 多个产品族:系统有多个产品族,且产品族可能继续增加
常见应用场景
- 跨平台UI开发:Windows风格、Mac风格、Linux风格
- 数据库访问:MySQL、Oracle、PostgreSQL的连接和命令
- 游戏开发:不同风格的道具、角色、场景
- 配置管理:不同环境(开发、测试、生产)的配置
与工厂方法的区别
| 特性 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建对象 | 单个对象 | 对象族(多个相关对象) |
| 工厂数量 | 多个工厂(每个产品一个) | 多个工厂(每个产品族一个) |
| 产品类型 | 一种产品 | 多种相关产品 |
| 扩展性 | 新增产品容易 | 新增产品族容易,新增产品类型困难 |
| 复杂度 | 较简单 | 较复杂 |
使用建议
- 需要创建单个产品:使用工厂方法模式
- 需要创建产品族:使用抽象工厂模式
- 产品族固定,产品类型可能增加:考虑使用其他模式
- 产品类型固定,产品族可能增加:使用抽象工厂模式
注意事项
⚠️ 抽象工厂模式虽然强大,但不要滥用:
- 如果产品族很少(1-2个),可以考虑使用工厂方法模式
- 如果产品类型很少(1-2个),可以考虑使用工厂方法模式
- 抽象工厂模式会增加类的数量,要权衡利弊
- 新增产品类型时,需要修改所有工厂类,违反开闭原则