1 意图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2 别名
Kit
3 动机
考虑一个支持多种视感(look - and - feel)标准的用户界面工具包,例如 Motif 和 Presentation Manager。不同的视感风格为诸如滚动条、窗口和按钮等用户界面“窗口组件”定义不同的外观和行为。为保证视感风格标准间的可移植性,一个应用不应该为一个特定的视感外观硬编码它的窗口组件。在整个应用中实例化特定视感风格的窗口组件类将使得以后很难改变视感风格。
4 适用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
5 结构
6 参与者
- AbstractFactory(WidgetFactory):声明一个创建抽象产品对象的操作接口。
- ConcreteFactory(MotifWidgetFactory,PMWidgetFactory):实现创建具体产品对象的操作。
- AbstractProduct(Windows,ScrollBar):—为一类产品对象声明一个接口。
- ConcreteProduct(MotifWindow,MotifScrollBar):定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct接口。
- Client:仅使用由AbstractFactory和AbstractProduct类声明的接口
7 协作
- 通常在运行时刻创建一个 ConcreteFactroy 类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。
- AbstractFactory 将产品对象的创建延迟到它的 ConcreteFactory 子类。
8 效果
- 它分离了具体的类(利)AbstractFactory 模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。
- 它使得易于交换产品系列(利)一个具体工厂类在一个应用中仅出现一次 — 即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。
- 它有利于产品的一致性(利)当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而 AbstractFactory 很容易实现这一点。
- 难以支持新种类的产品(弊)难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory 接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及 AbstractFactory 类及其所有子类的改变。
9 实现
- 将工厂作为单件一个应用中一般每个产品系列只需一个 ConcreteFactory 的实例。因此工厂通常最好实现为一个 Singleton。
- 创建产品AbstractFactory 仅声明一个创建产品的接口,真正创建产品是由 ConcreteProduct 子类实现的。最通常的一个办法是为每一个产品定义一个工厂方法(FactoryMethod)。一个具体的工厂将为每个产品重定义该工厂方法以指定产品。虽然这样的实现很简单,但它却要求每个产品系列都要有一个新的具体工厂子类,即使这些产品系列的差别很小。如果有多个可能的产品系列,具体工厂也可以使用 Prototype 模式来实现。具体工厂使用产品系列中每一个产品的原型实例来初始化,且它通过复制它的原型来创建新的产品。在基于原型的方法中,使得不是每个新的产品系列都需要一个新的具体工厂类。
-定义可扩展的工厂AbstractFactory 通常为每一种它可以生产的产品定义一个操作。产品的种类被编码在操作型构中。增加一种新的产品要求改变 AbstractFactory 的接口以及所有与它相关的类。一个更灵活但不太安全的设计是给创建对象的操作增加一个参数。该参数指定了将被创建的对象的种类。它可以是一个类标识符、一个整数、一个字符串,或其他任何可以标识这种产品的东西。实际上使用这种方法,AbstractFactory 只需要一个 “Make” 操作和一个指示要创建对象的种类的参数。
10 代码示例
AbstractFactory(WidgetFactory)
1
2
3
4
5interface WidgetFactory
{
void CreateWindow();
void CreateScrollBar();
}ConcreteFactory(MotifWidgetFactory,PMWidgetFactory)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class MotifWidgetFactory:WidgetFactory
{
void CreateWindow()
{
Window w=new MotifWindow();
}
void CreateScrollBar()
{
ScrollBar sb=new MotifScrollBar();
}
}
class PMWidgetFactory:WidgetFactory
{
void CreateWindow()
{
Window w=new PMWindow();
}
void CreateScrollBar()
{
ScrollBar sb=new PMScrollBar();
}
}AbstractProduct(Windows,ScrollBar)
1
2interface Windows{}
interface ScrollBar{}ConcreteProduct(MotifWindow,PMWindow,MotifScrollBar,PMScrollBar)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class MotifWindow:Windows
{
public MotifWindow()
{
Console.WriteLine("MotifWindow");
}
}
class PMWindow:Windows
{
public PMWindow()
{
Console.WriteLine("PMWindow");
}
}
class MotifScrollBar:ScrollBar
{
public MotifScrollBar()
{
Console.WriteLine("MotifScrollBar");
}
}
class PMScrollBar:ScrollBar
{
public PMScrollBar()
{
Console.WriteLine("PMScrollBar");
}
}Client:仅使用由AbstractFactory和AbstractProduct类声明的接口
1
2
3
4
5
6class Client
{
WidgetFactory factory=new MotifWidgetFactory();
factory.CreateWindow();
factory.CreateScrollBar();
}
11 已知应用
InterView 使用 “Kit” 后缀 [Lin92] 来表示 AbstractFactory 类。它定义 WidgetKit 和 DialogKit 抽象工厂来生成与特定视感风格相关的用户界面对象。InterView 还包括一个 LayoutKit,它根据所需要的布局生成不同的组成(composition)对象。
12 相关模式
- AbstractFactory 类通常用工厂方法(FactoryMethod)实现,但它们也可以用 Prototype 实现。
- 一个具体的工厂通常是一个单件(Singleton)。