抽象工厂模式定义
抽象工厂提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。类图如下
使用场景
在以下情况可以使用Abstract Factory模式
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
结构
AbstractFactory
– 声明一个创建抽象产品对象的操作接口。ConcreteFactory
– 实现创建具体产品对象的操作。Product
– 为一类产品对象声明一个接口(或者抽象)。ConcreteProduct
– 定义一个将被相应的具体工厂创建的产品对象。
– 实现Product的接口或者继承抽象。Client
– 仅使用由AbstractFactory和Product类声明的接口。
协作
- 通常在运行时刻创建一个ConcreteFactory类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。
- AbstractFactory将产品对象的创建延迟到它的ConcreteFactory子类。
效果
AbstractFactory模式有下面的一些优点和缺点:
它分离了具体的类
AbstractFactory模式帮助你控制一个应用创建的对象的类。由于一个工厂将创建产品对象的职责和过程封装起来了,所以它将调用者与实现类分离了。调用者通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。它使得易于交换产品系列
一个具体工厂类在一个应用中仅出现一次————即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。它有利于产品的一致性
当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而AbstractFactory很容易实现这一点。难以支持新种类的产品
难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变。
抽象工厂模式实现(Implement)
案例
现在实际的应用场景是这样的,现在工厂要生产笔记本和台式电脑两种类型的电脑,笔记本Laptop类和台式电脑DesktopComputer类都为抽象类,有自己的品牌,并且包含了CPU,GPU,RAM三个抽象类。CPU、GPU、RAM都各自有不同厂家型号的产品。两家工厂成都富士康和深圳富士康负责生产电脑,成都富士康生产Apple品牌的笔记本和Dell品牌的台式电脑;深圳富士康生产Dell品牌的笔记本和Apple品牌的台式机。
结构
整体的结构如下
代码实现
抽象工厂
台式电脑抽象类
笔记本电脑抽象类
CPU类、GPU类以及RAM类
|
|
|
|
Apple品牌的笔记本
代码太多,就不一一粘贴过来了,来看具体工厂类
Client调用代码,一个工厂完成了两种产品的创建
仔细看Client部分的代码,抽象工厂的好处都可以体现,它将调用者与实现类分离开了,并且更换产品系列非常容易,只需要将工厂进行替换就可以了,但是如果产品等级结构本身需要更改的时候就十分麻烦,需要修改所有的工厂角色,连抽象工厂也需要修改。在上面例子中,Laptop和DesktopComputer可以算作两个不同的等级结构,而Apple和Dell算作不同的产品族,AppleLaptop和DellLaptop是相同的等级结构,AppleLaptop和AppleDesktopComputer是相同的产品族,DellLaptop和DellDesktopComputer也是相同的产品族。
在抽象工厂模式中,增加产品族十分方便,可以与已有系统直接集成。但是增加新的产品等级结构会非常复杂,需要对原有系统进行大量修改,会违背开闭原则。
举个简单例子,如果现在工厂还要增加手机的生产线,也就是增加一个新的产品等级结构CellPhone,那么扩展起来十分复杂,所有的工厂类都会增加生产新产品的方法。但是工厂如果新引进一个电脑品牌HP,也就是增加一个新的产品族HP,那么扩展很方便,直接增加对应的实体并让对应的具体工厂去生产新的HP电脑就可以了。
属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族的产品可以是没有任何关系的对象,但是它们都有一些共同的约束。
比如上面的例子中Apple产品族中都预装了操作系统OS X,Dell产品族中都预装了操作系统Windows,一个产品族中会有一些共同的约束条件。
总结
抽象工厂和工厂方法两种模式看起来很相似,实质上是不同的,两者都符合开闭原则,但是侧重点不同。工厂方法模式在增加一个新的具体产品的时候,更加侧重的是一个产品的类型,好比上面的例子,工厂方法的目标是Laptop这个产品,通过子类继承来生产不同类型的Laptop,但是产品等级结构是单一的,生产Laptop的这个工厂不会再去生产台式电脑。而抽象工厂侧重的是多个产品等级,不仅仅是电脑品牌之间的区别,还有可能是台式电脑和笔记本电脑之间的区别,抽象工厂中会面向多个产品的等级结构。