一、引言
抽象工厂模式是所有形态工厂模式中最为抽象和最具一般性的形态。
抽象工厂提供一个创建一系列相关或相互依赖对象的接口。
简略类图如下:
左边的等级代表工厂等级结构,右边的两个分别代表不同产品的等级结构。
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂模式的用意。
分为三段理解:
-
一个系统需要消费多个抽象产品角色,这些抽象产品角色可以用Java接口或抽象类实现。工厂类复制创建抽象产品的实例描述如下:
由于Java接口或抽象类不能实例化,所以以上设计不成立。
-
根据里氏代换原则,任何接收父类型的地方,都应当能接收子类型。系统所需要的,是类型与这些抽象产品角色相同的一些实例,而不是抽象产品的实例。即抽象产品具体子类实例。
-
如果每个抽象产品都有多于一个的具体子类,工厂角色怎么知道实例化哪个子类呢?比如每个抽象产品有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应这两个具体产品角色。每个具体工厂角色仅负责某一个具体产品角色的实例化。每个具体工厂类负责创建抽象产品的某一个具体子类实例。
二、问题
抽象工厂模式面对的问题是多个产品等级结构的系统设计。
1.多产品等级结构
2.产品族
产品族是指位于不同产品等级机构中,功能相关联的产品组成的家族。每个产品族中含有产品的数目,与产品等级结构的数目是相等。产品的等级结构和产品族按不同方向划分,形成一个二维坐标系:
2.引进抽象工厂模式
如果采用工厂方法模式,要使用三个独立的工厂等级结构,由于这三个产品等级结构相似,会导致三个平行的工厂等级结构。随着产品等级结构增加,工厂方法模式所给出的工厂等级结构数目也会增加。
那么,是否可以使用同一工厂等级结构来对付相同或相似的产品等级结构?这就需要抽象工厂模式。同一个工厂等级结构复杂三个不同产品等级结构中的产品对象创建。
三、抽象工厂模式的结构
1.产品对象的创建问题
由于这两个产品族的等级结构相同,因此,使用同一个工厂族来处理两个产品族创建问题。工厂角色的设计方案:
由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个具体工厂角色都需要提供这两个工厂方法,分别用于创建两个等级结构的产品。
每个工厂角色有两个工厂方法,分别负责创建分属不同产品等级结构的产品对象。
抽象工厂模式涉及角色:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
四、在什么情况下使用抽象工厂模式
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。
这个系统的产品有多于一个产品族,而系统只消费其中某一组产品。
同属于一个产品族的产品是一起使用的,这一约束在系统设计中体现出来。
系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
五、开-闭原则
对于涉及到多个产品等级结构和多个产品族的系统,其功能增强:
- 增加新的产品族
- 增加新的产品等级结构
1.增加新的产品族
在产品等级结构数目不变的情况下,增加新的产品族,意味着在每个产品等级结构中增加多个新的具体(或抽象和具体)产品角色。
产品等级结构出现新元素,也向工厂等级结构加入对应新元素。即只需向系统加入新的具体工厂类,不需修改已有的工厂角色和产品角色。所以,在增加产品族时,支持开-闭原则。
2.增加新的产品等级结构
在产品族数目不变时,增加新的产品等级结构。要做到这一点,需要修改所有的工厂角色,给每个工厂类增加新的工厂方法,这显然违背了开-闭原则。
扩展新产品等级比较困难,不符合开闭原则。扩展新的产品族比较方便