ξ 14.1 引言
☆ 抽象工厂模式的用意:抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。
☆ 对抽象工厂模式理解的三个步骤:
① 当系统中有多个抽象产品角色的时候,假设产生抽象产品角色的是实现了抽象工厂角色的具体工厂角色。
② 阶段一的假设无法成立,因为抽象产品角色无法被实例化。根据里氏替代原则,可以让具体工厂角色产生抽象产品角色的实现类,即具体产品角色。
③ 如果抽象产品角色有多个具体实例即具体产品角色,那么工厂(具体和抽象)角色应该提供不同的方法产生不同的具体产品角色。
ξ 14.2 问题
☆ 产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。下图详细说明产品等级结构和产品族的关系:
从上图可以看出,对应的每一个产品族,都由一个具体工厂负责创建,在同一产品族中不同等级结构上的具体产品,由具体工厂的每个方法创建。
ξ 14.3 抽象工厂模式的结构
☆ 假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产品等级结构。那么为了将消费这些产品对象的责任和创建这些产品对象的责任分割开,可以引入抽象工厂模式。这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公共的工厂接口请求所需要的产品。下面举例说明这种结构:
图中有两个等级结构,A和B。两个产品族1和2。可以看到,对于一个产品族有一个实现了抽象工厂角色的具体工厂角色(ProductA1和ProductA2对应ConcreteCreator1,ProductA2和ProductB2对应ConcreteCreator2),而同一个产品族内不同的等级结构,对应具体工厂角色里面的不同方法(ProductA1和ProductA2对应factoryA方法,ProductB1和ProductB2对应factoryB方法)。下面是源代码:












































































ξ 14.4 在什么情况下应该使用抽象工厂模式
① 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是很重要的;
② 这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品;
③ 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
④ 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
ξ 14.7 “开-闭”原则
当抽象工厂模式中新加产品族的时候,只需要添加抽象工厂角色和抽象产品角色的具体角色并建立起相应的关系就可以,这个时候抽象工厂模式是支持“开-闭”原则的;
当增加产品等级结构时,需要改动抽象工厂角色和修改每个具体工厂角色,这个时候,抽象工厂模式是不满足“开-闭”原则的。
综合来看,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。
=============================
最后总结一下:
☆ 首先举一个比较具体的例子。在UI设计中,一般会有许多控件,比如按钮(Button)和文本框(Text),这里Button和Text就是两个等级结构的产品。而为了在Windows和Macintosh系统中提供不同的效果,需要有Windows Button、Windows Text,同理会有Macintosh Button和Macintosh Text,这里Windows和Macintosh就是两个产品族,下图说明了它们之间的关系:
下面是源代码:



























































































































































☆ 下面给出三种常见形态的工厂模式的相图,依次是抽象工厂模式、工厂方法模式和简单工厂模式: