抽象工厂模式是一种创建型设计模式,它的模式动机是:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
例如现在有两个农场:一个农场生产牛和萝卜,一农场生产羊和白菜。其中牛和羊属于动物类,是同一种类;萝卜和白菜属于蔬菜类,是同一种类。但牛和萝卜在一个农场生产,我们将二者称作同一产品族;羊和白菜在一个农场生产,是一个产品族。一个产品族内含有多个产品种类,抽象工厂模式是工厂方法模式的升级版,工厂方法模式只生产一个种类的产品,而抽象工厂模式可生产多个种类的产品。
使用该模式一般需要满足以下条件:
(1)系统中有多个产品族,每个具体工厂创建同一产品族但属于不同种类的产品;
(2)系统一次只可能消费其中某一族产品,即同族的产品一起使用;
抽象工厂模式的组成与工厂方法模式一样,为:(1)抽象产品类(2)抽象工厂类(3)具体产品类(4)具体工厂类
以上农场生产为例,依旧以每种产品内产品对象的定义不同为一个变化点;以new出不同对象为一个变化点。首先抽象出蔬菜类和动物类,两个种类的产品,抽象出两个抽象产品类,如下图1:
两个抽象产品类中的抽象方法在子类(具体产品类)中实现,会实现不同的产品属性,例如:牛和羊虽然都是一种产品,但单个产品的属性不同,羊是羊肉羊奶,牛是牛肉牛奶——这正是变化点。图2图3是具体产品类,定义了两种四个具体的产品:
由于每次new对象,不管是new白菜、萝卜还是羊、牛,对象都不同,这是一个变化点,所以要抽象出工厂类来创建对象,在这里工厂类就相当于农场,一个农场产多种产品,而不是像工厂方法模式中一个工厂产一种产品,所以抽象工厂类中需要有多个抽象方法,每个抽象方法负责创建一种产品对象,如下:
该抽象工厂类中的抽象方法在子类(具体工厂类)中实现,会new出不同的对象,这是第二个变化点。图5图6是两个具体工厂类,即两个产品族,实现了创建两种四个不同的产品对象:
抽象工厂模式实际上与工厂方法模式相差不大,只是在抽象工厂类中增加了抽象方法,以此来增加工厂里创建对象的种类,这种行为有好处也有坏处,好处就是:
(1)相对于工厂方法模式减少了系统中的类的个数;
(2)可在类的内部对产品族中的多种产品共同管理;
(3)当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
坏处就是当一个产品族中要增加一种产品时非常麻烦,所有的具体工厂类都要进行修改。
另外,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。
所以抽象工厂模式适用于:
(1)当需要创建的对象是一系列相互关联或相互依赖的产品族时
(2)系统中有多个产品族,但每次只使用其中的某一族产品。
(3)系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构