航通社 2018-01-05
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
这里新增一个概念,**产品族:**是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。
工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构,所以有个产品族的概念。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式中的所有产品都是来自同一个接口或抽象类,而抽象工厂模式中的产品则是来自不同的接口或抽象类。
抽象工厂模式是工厂方法模式的升级版本,在有多个业务,或者多个分类的情况下,抽象工厂模式比较适合。
前几天我写了工厂方法模式的文章,设计模式(2)-工厂方法模式详解(易懂)
文章里举例了手机工厂生产手机的例子,我们继续用这个例子来分析这两个模式。
首先来回忆一下工厂方法模式的例子:一个手机工厂生产华为和小米两种手机,模型图如下:
从模型上可以发现,两种手机在一个等级结构,也就是都实现或者集成了同一个接口或抽象类。
还以手机为例,现在加入了手机尺寸的要求,模型如下:
首先要知道一个概念,产品族,文章开头我已经定义了。
从上面模型可以发现:
6.0英寸华为手机A1与6.0英寸的小米手机B1属于一个产品族,5.5英寸华为手机A2与5.5英寸小米手机B2属于一个产品族;Factory1表示生产6.0英寸的手机,Factory2表示生产5.5英寸的手机。
抽象工厂模式中的抽象工厂类中的创建方法与产品族的个数有关。
有N个产品等级结构就会有N个实现工厂类。
我们拿上面的抽象工厂实例模型举例:
1.首先看一下两种手机的抽象产品类:
public abstract class AbstractHUAWEI { //华为手机共同的方法,比如品牌 public void commonMethod(){ } //相同的方法,不同的实现。比如尺寸,型号等等 public abstract void dosomething(); }
public abstract class AbstractMI { //小米手机共同的方法,比如品牌 public void commonMethod(){ } //相同的方法,不同的实现。比如尺寸,型号等等 public abstract void dosomething(); }
2.两种手机对应的产品实现类
public class HUAWEI_A1 extends AbstractHUAWEI{ @Override public void dosomething() { Log.i("qzs","我是6.0英寸的华为手机A1"); } } public class HUAWEI_A2 extends AbstractHUAWEI { @Override public void dosomething() { Log.i("qzs","我是5.5英寸的华为手机A2"); } } public class MI_B1 extends AbstractMI { @Override public void dosomething() { Log.i("qzs","我是6.0英寸的小米手机B1"); } } public class MI_B2 extends AbstractMI { @Override public void dosomething() { Log.i("qzs","我是5.5英寸的小米手机B1"); } }
3.抽象工厂类
public abstract class AbstractFactory { //6.0英寸手机 public abstract AbstractHUAWEI createSize1(); //5.5英寸手机 public abstract AbstractMI createSize2(); }
4.两个工厂实现类
public class Factory1 extends AbstractFactory { @Override public AbstractHUAWEI createSize1() { return new HUAWEI_A1(); } @Override public AbstractMI createSize2() { return new MI_B1(); } }
public class Factory2 extends AbstractFactory { @Override public AbstractHUAWEI createSize1() { return new HUAWEI_A2(); } @Override public AbstractMI createSize2() { return new MI_B2(); } }
5.调用
AbstractFactory factory1=new Factory1(); AbstractFactory factory2=new Factory2(); //生产A1 AbstractHUAWEI a1=factory1.createHUAWEI(); // a1.dosomething(); //生产A2 AbstractHUAWEI a2=factory2.createHUAWEI(); // a2.dosomething(); //生产B1 AbstractMI b1=factory1.createMI(); // b1.dosomething(); //生产B2 AbstractMI b2=factory2.createMI(); // b2.dosomething();
从调用类可以看出,创建的生产对象过程与实现类无关。
1.优点
隔离了具体类(从调用类的代码可以看出),非公开。
增加产品下的系列也就是增加具体的实现工厂类很方便,符合“开闭原则”(比如上面的例子中我在两种手机下又新增了一个5.0英寸的,直接加一个新的具体工厂类就可以了)
2.缺点
抽象工厂模式的产品族扩展是很难的,拿上面的手机举例,如果我增加个一个手机品牌OPPO,那么由两个品牌变成三个品牌,试试改一下会发现:首先要更改抽象工厂类,然后会发现所有的类基本上都跟着动了。改变了抽象类和接口,这是大忌!
类文件增加过快
参考资料《大话设计模式》《设计模式之禅》欢迎大家关注我的微信公众号:安卓干货铺