Abstract Factory Method(抽象工厂): this makes an instance of several derived classes based on interfaced data of events. 提供一个创建一系列相关或者互相依赖对象的接口,而无需指定它们具体的类。
动机
支持多「look-and-feel」、多平台的系统。
适用性
一个系统要独立于它的产品的创建、组合和表示时;一个系统要由多个产品系列中的一个来配置时;当需要强调一系列相关产品对象的设计以便于它们聚合使用时;当你提供一个产品类库,而只想要展示它们的接口而非实现的时候。
代码结构
abstract class WidgetFactory {
createScrollBar();
createWindow();
}
class MacWidgetFactory extends WigetFactory {}
class WidnowsWidgetFactory extends WigetFactory {}
abstract class Window {}
class MacWindow extends Window {}
class WindowsWindow extends Window {}
abstract class ScrollBar {}
class MacScrollBar extends ScrollBar {}
class WindowsScrollBar extends ScrollBar {}
// 本质上这里使用 FactoryMethod 来实现了 AbstractFactory 的设计模式细节
const myMacFactory = new MacWidgetFactory().createWindow();
const windowsScrollBar = new WindowsWidgetFactory().createScrollBar();
客户最终只会和定义的抽象类的接口进行互动,而不会关心具体类的指定和实现。
Creates an instance of several families of classes without detailing concrete classes. 要注意的是,「抽象工厂」提供的针对产品类族构建的思想,而在实现的时候,构造类和对象的时候,我们可以使用适合的方法构建,比如 Prototype
模式来创建对象,而是用 Bridge
模式来分离抽象和具体的实现。
效果
- 【Pro】分离了具体的类。将客户和「类」的实现分离,客户只需要通过它们的抽象接口来操作实例。
- 【Pro】使得它易于变换产品系列。
- 【Pro】有利于产品体系下的「一致性」。
【Con】难以支持新种类的产品,因为接口确定了产品集合,扩展接口会导致所有子类发生变更。
实现
工厂对象,最好是「单例」。
AbstractFactory
通常只声明一个创建产品的接口,真正创建产品的过程是由具体的产品子类来实现的。最常用的方法是为每一个产品定义一个工厂方法(Factory Method)以动态创建产品实例。- 比如上面 case 中的:
createWindow() / createScrollBar()
- 比如上面 case 中的:
- 上述方法虽然实现简单但是每个系列产品都需要定义「子类」,当然我们也可以选择使用
Prototype
的设计模式来实现,以使得并非每一个新的产品都需要一个子类来定义。 - 我们还可以考虑,参数化构建对象的工厂方法,比如:
create('window')
增加动态灵活性。 - 子类通常可以使用
FactoryMethod
实现,也可以使用Prototype
来实现。
实践
- UI 编排设计器中,表示节点(PresentationNode)可能是多种类的,我们可以构筑一个抽象工厂来批量生产我们想要的 Node 类;