Abstract Factory Method(抽象工厂): this makes an instance of several derived classes based on interfaced data of events. 提供一个创建一系列相关或者互相依赖对象的接口,而无需指定它们具体的类。

动机

支持多「look-and-feel」、多平台的系统。

适用性

一个系统要独立于它的产品的创建、组合和表示时;一个系统要由多个产品系列中的一个来配置时;当需要强调一系列相关产品对象的设计以便于它们聚合使用时;当你提供一个产品类库,而只想要展示它们的接口而非实现的时候。

代码结构

  1. abstract class WidgetFactory {
  2. createScrollBar();
  3. createWindow();
  4. }
  5. class MacWidgetFactory extends WigetFactory {}
  6. class WidnowsWidgetFactory extends WigetFactory {}
  7. abstract class Window {}
  8. class MacWindow extends Window {}
  9. class WindowsWindow extends Window {}
  10. abstract class ScrollBar {}
  11. class MacScrollBar extends ScrollBar {}
  12. class WindowsScrollBar extends ScrollBar {}
  13. // 本质上这里使用 FactoryMethod 来实现了 AbstractFactory 的设计模式细节
  14. const myMacFactory = new MacWidgetFactory().createWindow();
  15. 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()
  • 上述方法虽然实现简单但是每个系列产品都需要定义「子类」,当然我们也可以选择使用 Prototype 的设计模式来实现,以使得并非每一个新的产品都需要一个子类来定义。
  • 我们还可以考虑,参数化构建对象的工厂方法,比如:create('window') 增加动态灵活性。
  • 子类通常可以使用 FactoryMethod 实现,也可以使用 Prototype 来实现。

实践

  • UI 编排设计器中,表示节点(PresentationNode)可能是多种类的,我们可以构筑一个抽象工厂来批量生产我们想要的 Node 类;