文章摘要: 提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
简介
简要说明
- 抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式。
- 提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
- 抽象工厂允许客户程序通过抽象接口创建产品,而无需知道(或关心)实际产出的具体产品类。
主要功能
- 创建产品族: 抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
- 封装创建逻辑: 将具体类的实例化过程封装在抽象工厂的实现中,客户端代码只需要与抽象工厂及其产品接口交互。
- 切换产品族: 允许系统通过切换不同的具体工厂实现,来切换整个产品族的生产,从而在不修改客户端代码的情况下,实现不同产品族之间的切换。
- 提高可扩展性: 新的产品族可以通过增加新的具体工厂类来实现,而不需要修改现有的系统代码。
- 降低耦合度: 客户端代码与具体产品的实现解耦,只依赖于抽象层,使得系统更加模块化,易于维护和扩展。
注意事项
- 开闭原则:添加新的产品族时,应该不修改原有代码,通过增加新的具体工厂类来实现,但添加新的产品等级结构需要修改抽象工厂和所有具体工厂类,违反了开闭原则。
- 复杂度:抽象工厂可能会增加系统的复杂度,尤其是产品族较多时,需要管理和维护的类会比较多。
- 类爆炸:随着产品族和产品等级的增多,系统中类的数量会急剧增加,增加了系统的复杂性。
- 难以扩展新产品族:如果需要添加新的产品族,需要修改抽象工厂的接口,这会导致所有具体工厂类都需要修改,这通常是比较困难的。
- 不要滥用:并不是所有的工厂类都应该使用抽象工厂模式,只有当确实存在多个产品族,并且它们之间存在逻辑上的关联时,才考虑使用抽象工厂模式。
适用场景
- 一组具有相同约束的对象:当你需要创建的对象是一系列相关的产品族,而不是一个单一的产品时,可以使用抽象工厂模式。
- 系统需要多个产品族:一个系统不应当依赖于产品实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 产品对象的创建逻辑有可能改变:抽象工厂允许将创建逻辑的变化限制在具体工厂内部,而不影响客户端代码。
- 需要隔离多个并行的产品族:在程序运行时,系统可能需要根据上下文选择创建哪一个产品族的对象。
Java 8
案例
// 定义一个形状接口和两个具体的形状类
// 形状接口
interface Shape {
void draw();
}
// 圆形类
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
// 正方形类
class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
// 定义一个抽象工厂接口和两个具体的工厂类
// 抽象工厂接口
interface AbstractFactory {
Shape getShape(String shapeType);
}
// 具体工厂类 - 生产圆形
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("SQUARE")) {
return new Square();
}
return null;
}
}
// 创建一个工厂生成器类和一个客户端类来使用抽象工厂
// 工厂生成器类
class FactoryProducer {
public static AbstractFactory getFactory(String choice) {
if (choice.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
}
return null;
}
}
// 客户端类
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
// 获取形状工厂
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
// 获取圆形对象并调用其 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
// 获取正方形对象并调用其 draw 方法
Shape shape2 = shapeFactory.getShape("SQUARE");
shape2.draw();
}
}
注释
- 在这个例子中,FactoryProducer 类的 getFactory 方法根据传入的参数返回相应的工厂对象。
- 客户端通过 FactoryProducer 获取到 ShapeFactory,然后使用 ShapeFactory 来创建具体的形状对象,并调用它们的 draw 方法。