3.1-AbstractFactory「Kit」-抽象工厂-创建型模式

又称 Kit

Abstract Factory 抽象工厂

用途

用途:提供一个接口以创建一系列相关或相互依赖的对象,而无须指定它们具体的类。

示例

示例: GUI 程序需要支持 Motif 和 PW 这 2 种视窗标准:

  • 抽象工厂提供 CreateXXX 接口生产抽象组件 XXX,用户调用该函数获取 XXX 组件
  • 抽象工厂的具象工厂子类实现 CreateXXX 接口,生产自己这种类型的具象组件 YYXXX(YYWindow,YYScrollBar,…)
  • 客户仅与抽象类定义的接口交互,而不使用特定的具体类的接口

结构

  • AbstractFactory:声明一个创建抽象产品对象的接口
  • ConcreteFactory:实现创建具体产品对象的操作
  • AbstractProduct:为一类产品对象声明一个接口
  • ConcreteProduct:定义具体的产品对象,实现 AbstractProduct 接口
  • Client:只使用 Abstract 的接口

协作过程:

  • 通常在运行时创建一个 ConcreteFactroy 类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。
    • 说明:简单实现时,AbstractFactory 和 ConcreteFactory 可以合二为一
  • AbstractFactory 将产品对象的创建延迟到它的 ConcreteFactory 子类。

适用条件

  • 系统独立于产品的创建、组合和表示
  • 系统包含多个产品系列,用其中的一种进行表示
  • 强调一个系列的产品设计,以便联合使用
  • 提供产品类库,但是只显示接口而隐藏实现

优缺点

  • 优点:
    • 分离实现:工厂封装了创建产品对象的责任和过程,将客户和具体实现分离。客户只操作抽象接口,避免硬编码具体的类名
    • 易于切换产品系列
    • 有利于产品风格的一致性:应用一次只能使用同一个系列中的对象,这有利于维护一致性
  • 缺点:
    • 难以支持新种类的产品:AbstractFactory 定义了可被其创建的产品集合,创建新产品意味着需要扩展 AbstractFactory 和其所有子类的接口。

实现的注意事项

  • 工厂使用单例模式:一个应用通常每个产品系列只需要一个 ConcreteFactory 实例
  • 创建产品的方法
    • 常用方法:为每个产品定义一个工厂方法,具体的工厂为每个工厂重载该工厂方法以指定产品
    • 简化具体工厂类:可以使用 Prototype 模式实现具体工厂。具体工厂使用产品系列中每一个产品的原型实例来初始化,且它通过复制它的原型来创建新的产品。基于原型的方法使得并非每个新的产品系列都需要一个新的具体工厂类。
  • 可扩展的工厂
    • 通常增加一种新的产品要求改变 AbstractFactory 的接口以及所有与它相关的类。
    • 一个更灵活但不太安全的设计是给创建对象的操作增加一个参数(例如类标识符,字符串,整数索引等)该参数指定了将被创建的对象的种类。使用这种方法 AbstractFactory 只需要一个“Make”操作和一个指示要创建对象的种类的参数。
    • 客户需要使用执行向下类型转换(downcast,例如 cpp 中的 dynamic_cast)才能获得具体的子类型,而这会带来安全隐患