1. 女娲的失误

上一节学习了工厂模式,女娲运用了该模式成功创建了三个人种,可是问题来了,她发现没有性别……这失误也忒大了点吧……竟然没有性别,那岂不是……无奈,只好抹掉重来了,于是所有人都被消灭掉了,重新造人。

女娲开始分析了,既然要区别男女,那么生产人种的工厂(八卦炉)要重新改造了,因为一个设备要么全男性,要么全女性。所以只能将八卦炉拆开了,把原先的一个变两个,并且略加修改,变成女性八卦炉和男性八卦炉,这样就可以了。于是女娲开始准备生产了,她先画了个示意图如下:

这个图虽然有点大,但是不复杂,她将HumanFactory接口用两个新的接口继承,分别带有男性和女性特征;将原来具体的Human类也改成了抽象类,用两个具体的Human类去继承。下面我们看看女娲的实现:

先看Human接口和它的几个抽象类:

//定义抽象人类接口
public interface Human {
public void getColor();
public void talk();
public void getSex(); //多了个性别
} //定义抽象黄种人类
public abstract class AbstractYellowHuman implements Human {
@Override
public void getColor() {
System.out.println("Yellow color");
}
@Override
public void talk() {
System.out.println("Yellow people");
}
}
//抽象黑种人和白种人就不写了,跟抽象黄种人道理一样
//略 //黄种人男性类
public class MaleYellowHuman extends AbstractYellowHuman {
@Override
public void getSex() {
System.out.println("Yellow man!");
}
}
//黄种人女性类略

以上省略了类似的代码,实现方式都一样,很简单,就不啰嗦了,到此为止,女娲把人种都定义好了,下面就是去定义八卦炉了:

//抽象工厂接口的定义
public interface HumanFactory {
public Human createYellowHuman();
public Human createBlackHuman();
public Human createWhiteHuman();
} //生产女性的八卦炉
public class FemaleFactory implements HumanFactory {
@Override
public Human createYellowHuman() {
return new FemaleBlackHuman();
}
@Override
public Human createBlackHuman() {
return new FemaleBlackHuman();
}
@Override
public Human createWhiteHuman() {
return new FemaleWhiteHuman();
}
} //生产男性的八卦炉
public class MaleFactory implements HumanFactory {
@Override
public Human createYellowHuman() {
return new MaleYellowHuman();
}
@Override
public Human createBlackHuman() {
return new MaleBlackHuman();
}
@Override
public Human createWhiteHuman() {
return new MaleWhiteHuman();
}
}

好了,现在人种有了,八卦炉也有了,女娲终于可以再次造人了!

public class NvWa {
public static void main(String[] args) {
HumanFactory maleHumanFactory = new MaleFactory(); //第一条生产线:男性生产线
HumanFactory femaleHumanFactory = new FemaleFactory(); //第二条生产线:女性生产线 //生产线建立完毕,开始造人
Human maleYellowHuman = maleHumanFactory.createYellowHuman(); //造黄色男性
Human femaleYellowHuman = femaleHumanFactory.createYellowHuman(); //造黄色女性 System.out.println("--生产一个黄色女性--");
femaleYellowHuman.getColor();
femaleYellowHuman.talk();
femaleYellowHuman.getSex(); System.out.println("--生产一个黄色男性--");
maleYellowHuman.getColor();
maleYellowHuman.talk();
maleYellowHuman.getSex();
/*
* ……
*/
}
}

到这里,抽象工厂模式的思路算是理清了,下面看看抽象工厂模式的定义。

2. 抽象工厂模式的定义

抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes. 即为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。它的通用类图如下:

抽象工厂模式是工厂模式的升级版,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂欧式的通用源代码,首先有两个互相影响的产品线(也叫产品族),例如汽车的左门和右门,这两个数量应该是相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的,我们先看看两个产品族的类图:

注意类图上的圈圈、框框相对应,两个抽象的产品类可以有关系,例如共同继承或实现一个抽象类或接口,其源代码如下:

public abstract class AbstractProductA {
//每个产品共有的方法
public void shareMethod() { }
//每个产品相同的方法,不同的实现
public abstract void doSomething();
}

两个具体的产品实现类的代码如下:

public class productA1 extends AbstractProductA {
public abstract void doSomething(){
System.out.println("产品A1的实现方法");
}
} public class productA2 extends AbstractProductA {
public abstract void doSomething(){
System.out.println("产品A2的实现方法");
}
}

产品B与此类似,不再赘述。抽象工厂类AbstractCreator的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂类定义了两个产品族的产品创建,如下:

public abstract class AbstractCreator {
//创建A产品家族
public abstract AbstracProductA createProductA();
//创建B产品家族
public abstract AbstracProductB createProductB();
//如果有N个产品族,这里就应该有N个创建方法
}

如何创建一个产品呢?这是由具体的实现类来完成的,Creator1和Creator2代码如下:

public class Creator1 extends AbstractCreator {
//只生产产品等级为1的A产品
public AbstracProductA createProductA(){
return new ProductA1();
}
//只生产产品等级为1的B产品
public AbstracProductB createProductB() {
return new ProductB1();
}
} public class Creator2 extends AbstractCreator {
//只生产产品等级为1的A产品
public AbstracProductA createProductA(){
return new ProductA2();
}
//只生产产品等级为1的B产品
public AbstracProductB createProductB() {
return new ProductB2();
}
}

注:有M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。

在具体的业务中就可以生产一个与实现无关的对象了,如:

public class AbstractFactoryTest {
public static void main(String[] args) {
AbstractCreator creator1 = new Creator1();
AbstractCreator creator2 = new Creator2();
AbstractProductA a1 = creator1.createProductA();
AbstractProductA a2 = creator2.createProductA(); AbstractProductB b1 = creator1.createProductB();
AbstractProductB b2 = creator2.createProductB(); //……
}
}

3. 抽象工厂模式的优缺点

3.1 优点

1)封装性。每个产品的实现类不是高层模块要关心的,它要关心的是接口,是抽象,它不关心对象是如何创建出来的,这都由工厂类负责的,只要知道工厂类是谁,我就能创建一个需要的对象,省时省力。

2)产品族内的约束为非公开状态。例如生产男女比例的问题上,猜想女娲娘娘肯定有自己的打算,那么在抽象工厂模式中,这些约束都在工厂内里面实现的。

3.2 缺点

抽象工厂模式最大的缺点就是产品族扩展非常困难。如果我们要增加一个产品C,也就是说产品族由原来的A和B增加到3个,那么我们首先要在抽象类AbstractCreator中增加createProductC()方法,然后两个实现类都要修改……说到这里,已经知道了扩展的弊端了……

注意这里是产品族扩展比较困难,而不是产品等级扩展困难。产品等级扩展还是非常容易的,增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向扩展容易,纵向扩展难。

抽象工厂模式就介绍这么多,如有错误之处,欢迎留言指正~

最新文章

  1. 【DP】HDU 1260
  2. 理解 Keystone 核心概念 - 每天5分钟玩转 OpenStack(18)
  3. 【ipv6惹的祸】curl 超时
  4. hdu Hike on a Graph
  5. 影响 PHP 行为的扩展和网络函数
  6. php实现验证码
  7. iOS 导航控制器返回栈中的某一控制器
  8. PHP 练习租房
  9. Poj 2159 / OpenJudge 2159 Ancient Cipher
  10. Oracle Pivot学习心得
  11. sublime text 调出结果输出框
  12. Selenium2 (python)
  13. 求复变函数的 Taylor 展式与 Laurent 展式[华中师范大学2010年复变函数复试试题]
  14. sql server 性能调优之 资源等待SOS_SCHEDULER_YIELD
  15. 小程序支持打开APP了 还有小程序的标题栏也可以自定义
  16. 第11课 std::bind和std::function(2)_std::bind绑定器
  17. apicloud 第一篇
  18. input输入框只能输入正整数正则
  19. 怎样取消老毛桃软件赞助商---只需在输入框中输入老毛桃官网网址“laomaotao.org”
  20. Python开发【Django】:图片验证码、KindEditor

热门文章

  1. CodeForces 617A Elephant
  2. 基于Keepalvied的Mysql主主漂移(切换)
  3. 21、手把手教你Extjs5(二十一)模块Form的自定义的设计
  4. EQueue - 一个C#写的开源分布式消息队列的总体介绍(转)
  5. Android L(5.0)源码之图形与图像处理之简单图片——Bitmap
  6. tp框架
  7. BZOJ2733 [HNOI2012]永无乡 【线段树合并】
  8. CoordinatorLayout学习笔记
  9. 分布式事务 & 两阶段提交 & 三阶段提交
  10. handler的使用