抽象工厂模式
概述
《设计模式》中对抽象工厂(Abstract Factory) 模式的意图描述如下:
提供一个接口以创建一系列相关或相互依赖的对象,而无需指定它们具体的类
一般抽象工厂中的类结构如下图所示:
每个组件的介绍如下:
AbstractFactory
:一个创建抽象产品对象的接口ConcreateFactory
:创建具体产品的实现类AbstractProduct
:对一类产品的统一抽象ConcreateProduct
:实际的产品对象Client
:用于访问AbstractFactory
和AbstractProduct
的客户端对象
具体示例
假设现在有一个需求,需要能够灵活地创建多种类型的风格 UI
组件(如菜单、滚动条等),首先我们需要定一个抽象接口,规定相关的创建行为:
public interface UIFactory {
Menu createMenu(); // 创建 UI 的菜单栏组建
ScrollBar createScrollBar(); // 创建对滚动条组建
Window createWindow(); // 创建窗口组件
}
现在访问该 UI
工厂的对象 Client 是另一个与之相互隔离的对象,比如说一个文本编辑器对象,需要通过该 UI
工厂对象在自己的领域中添加对应的 UI
组件:
public class TextEditor {
public TextEditor createTextEditor(UIFactory factory) {
TextEditor editor = new TextEditor();
editor.setMenu(factory.createMenu());
editor.setScrollBar(factory.createScrollBar());
editor.setWindow(factory.createWindow());
return editor;
}
}
现在,具体的文本编辑器的创建已经很好地处理了和 UI
组件之间的依赖关系,使得系统之间的耦合程度大大减小
如果现在需要使得文本编辑器的风格是暗色的,那么我们只需要定义一个实现了 UIFactory
的暗色工厂,将它传给 TextEditor
进行创建即可:
public class BlackUIFactory implements UIFactory {
@Override
public Menu createMenu() {return new BalckMenu();}
@Override
public ScrollBar createScrollBar() {return new BlackScrollBar();}
@Override
public Window createWindow() {return new BlackWindow();}
}
而随着时间的推移,可能会希望能够提供极简风格的组件,那么我们同样可以横向拓展丰富系统的功能:
public class SimpleUIFactory implements UIFactory {
@Override
public Menu createMenu() {return new SimpleMenu();}
@Override
public ScrollBar createScrollBar() {return new SimpleScrollBar();}
@Override
public Window createWindow() {return new SimpleWindow();}
}
当需要替换不同风格的组件时,只需要传入不同的 UIFactory
实例即可,而无需关心实际的实例内容
总结
抽象工厂模式存在以下的一些优点:
- 抽象工厂分离了具体的类,客户端只需要知道抽象接口即可实现操作实例的逻辑,降低了系统的耦合程度
- 使得产品系列的交换变得容易。从上面的示例中我们可以看到,当希望修改组件的风格时,只需要改变传入的具体工厂实例
- 有利于产品的一致性。当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,而通过
AbstractFactory
则很容易实现这一点
当然,使用抽象工厂模式也存在一些不足,最大的不足之处便是不支持纵向扩展,即一个抽象工厂很难生产新的产品。这是因为 AbstractFactory
接口确定一个可以创建的产品集合,而如果需要生产新的产品的话,将会涉及到所有子类的改动
参考:
[1] 《设计模式—可复用面向对象基础》