【设计模式笔记15】:抽象工厂模式示例和小结 - 实践
5. 模式代码分析
- a. 抽象工厂 (AbstractFactory)
- 它定义了所有具体工厂必须实现的一组方法,用于创建一系列产品。每个方法都返回一个抽象产品类型。
public abstract class AbstractFactory {
// 创建产品A的抽象方法
public abstract AbstractProductA createProductA();
// 创建产品B的抽象方法
public abstract AbstractProductB createProductB();
}
- b. 具体工厂 (ConcreteFactory)
- 它继承抽象工厂,实现其中的抽象方法,以创建属于同一个产品族的一组具体产品。
public class ConcreteFactory1 extends AbstractFactory {
// 实现创建产品A的方法,返回具体产品A1
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
// 实现创建产品B的方法,返回具体产品B1
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
- c. 客户端 (Client)
- 客户端代码只依赖于抽象工厂和抽象产品。它通过一个具体工厂的实例来创建一组产品,然后使用这些产品。
- 在实际应用中,具体工厂的实例通常通过依赖注入或配置文件来获取,而不是在代码中硬编码
new ConcreteFactory1(),这样可以轻松切换整个产品族。
6. 模式实例与解析:软件皮肤库
- a. 实例背景
- 一个软件系统需要支持界面皮肤(Skin)的切换功能,例如提供一套“春天风格 (Spring)”的皮肤和一套“夏天风格 (Summer)”的皮肤。
- 每套皮肤都包含一组风格统一的UI控件,如按钮(Button)、文本框(TextField)、组合框(ComboBox)。
- 当用户选择一套皮肤时,界面上所有的控件都应该切换为该皮肤对应的风格。

- b. 角色映射
- 抽象工厂 (AbstractFactory):
SkinFactory接口,定义了创建所有UI控件的抽象方法(createButton(),createTextField()等)。 - 具体工厂 (ConcreteFactory):
SpringSkinFactory和SummerSkinFactory类,分别用于创建春天风格和夏天风格的UI控件族。 - 抽象产品 (AbstractProduct):
Button,TextField,ComboBox等接口,定义了UI控件的通用行为。 - 具体产品 (ConcreteProduct):
SpringButton,SummerButton,SpringTextField,SummerTextField等,是具体风格的UI控件实现。
- 抽象工厂 (AbstractFactory):

如图UML类图,清晰地展示了
SkinFactory的继承体系,以及Button,TextField,ComboBox三个并行的产品继承体系,以及Client与它们之间的依赖关系。
- c. 客户端调用与结果
- 客户端通过配置文件动态获取具体的皮肤工厂对象。
- 然后使用这个工厂创建一套完整的UI控件,并调用它们的
display方法来展示。 - 由于使用的是同一个工厂,可以保证创建出的所有控件都属于同一个皮肤系列(产品族),实现了风格的统一。
7. 模式优缺点与扩展性分析
优点(开闭原则的体现)
- 易于交换产品族:当需要更换整个产品系列时(例如从Spring皮肤换到Summer皮肤),只需改变具体工厂的实例即可,客户端代码无需任何修改。
- 增加新的产品族很方便:如果需要增加一个新的产品族(例如“秋天风格”皮肤),只需要增加一个新的具体工厂(
FallSkinFactory)和一套新的具体产品(FallButton等)即可,无需修改原有代码。在这个维度上,它符合开闭原则。
缺点
- 增加新的产品等级结构困难:如果需要增加一个新的产品类型(例如增加一个新的UI控件“滚动条 ScrollBar”),那么需要修改
AbstractFactory接口,增加一个新的抽象方法createScrollBar()。这将导致所有已有的具体工厂类(SpringSkinFactory,SummerSkinFactory等)都必须进行修改,以实现这个新方法。在这个维度上,它严重违反了开闭原则。
- 增加新的产品等级结构困难:如果需要增加一个新的产品类型(例如增加一个新的UI控件“滚动条 ScrollBar”),那么需要修改
与工厂方法模式的关系
- 当抽象工厂中只有一个创建产品的抽象方法时,抽象工厂模式就退化为了工厂方法模式。因此,可以认为工厂方法模式是抽象工厂模式的一个特例。
8. 模式适用环境
在以下情况下可以考虑使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将被一起使用,这一约束必须在系统的设计中体现出来。(例如,Spring风格的按钮必须和Spring风格的文本框搭配使用)。
- 系统提供一个产品类的库,所有的产品都以同样的方式接口出现,从而使客户端不依赖于具体实现。
浙公网安备 33010602011771号