链接地址:http://www.xx566.com/detail/135.html
上一篇,我们学习了工厂方法模式(Factory Method),它对简单工厂模式(Simple Factory)做 了深层次的抽象,它定义了一个抽象工厂类,当系统中需要加入新的产品,我们只需要加入一个产品类和它所对应的工厂类,不需要修改客户端代码,也不需要修改 抽象工厂类和其它具体的工厂角色,但是,一个抽象的工厂类往往不能够满足我们现实中的需要,这时候就需要用到抽象工厂(Abstract Factory)模式了。 以上一篇的手机工厂为例,现实生产中,我们的工厂可能还需要进行平板电脑的生产和供应,当然我们可以通过工厂方法模式再抽象出一个pad工厂,进行pad 的生产,但随着工厂业务水平的提升,我们以后可能会抽象出许许多多类似的工厂,我们对工厂的维护的成本将会增加,人力物力财力的支出也会增大,这时候,我 们可以通过抽象工厂模式改造我们的工厂。 首先,我们来简单的了解一下抽象工厂模式的定义(来自维基百科),如下:抽象工厂模式提供了一种方式, 可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。 简单来说,抽象工厂模式就是把手机工厂和pad工厂抽象成一个整体的工厂,负责手机和pad的生产,它是对工厂方法模式的再一次抽象。它与工厂方法模式的 最大区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,我们来看一下抽象工厂模式的UML类图,如下(来自维基百科):
从上图中,我们可以看到,抽象工厂模式包含以下四种角色,与工厂方法模式是比较相似的,如下:
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它与应用系统商业逻辑无关,一般由接口或抽象类担任,具体的工厂角色必须实现此接口或继承此抽象类。
具体工厂(Concrete Factory)角色:具体工厂角色直接在客户端的调用下创建产品的实例,它包含选择合适的产品对象的逻辑,这个逻辑是与应用系统的商业逻辑紧密相关。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口,通常使用抽象类或接口担任。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例,这是客户端最终需要的东西,内部包含了应用系统的商业逻辑。
接下来,我们通过修改工厂方法模式(Factory Method)中的代码,继续抽象工厂模式的学习和理解,首先,我们抽象出两种产品系列,Mobile和Pad,代码如下:
/** * 产品系列:Mobile * User: Realfighter * Date: 2014/8/26 * Time: 11:56 */ public interface Mobile { public String brand();//品牌 public double price();//手机价格 } /** * User: Realfighter * Date: 2014/8/26 * Time: 11:57 */ public interface Pad { public double size();//尺寸 public String face();//外观 }
有了抽象的产品,我们就需要计划生产具体的产品了,Mobile系列,客户需要Nokia和Iphone,Pad系列,客户需要AndroidPad和Ipad,具体代码如下:
/** * Mobile系列:Nokia * User: Realfighter * Date: 2014/8/26 * Time: 12:04 */ public class Nokia implements Mobile{ @Override public String brand() { return "Nokia"; } @Override public double price() { return 3000.0; } //这里为了方便调试,重写了toString @Override public String toString() { return this.brand() + ":" + this.price(); } } /** * Mobile系列:Iphone * User: Realfighter * Date: 2014/8/26 * Time: 12:06 */ public class Iphone implements Mobile { @Override public String brand() { return "Iphone"; } @Override public double price() { return 5000.0; } //这里为了方便调试,重写了toString @Override public String toString() { return this.brand() + ":" + this.price(); } } /** * Pad系列:AndroidPad * User: Realfighter * Date: 2014/8/26 * Time: 12:06 */ public class AndroidPad implements Pad { @Override public double size() { return 10.4; //10.4寸 } @Override public String face() { return "better"; } //这里为了方便调试,重写了toString @Override public String toString() { return "AndroidPad:" + this.size() + "," + this.face(); } } /** * Pad系列:Ipad * User: Realfighter * Date: 2014/8/26 * Time: 12:07 */ public class Ipad implements Pad { @Override public double size() { return 9.7; //9.7寸 } @Override public String face() { return "best"; } //这里为了方便调试,重写了toString @Override public String toString() { return "Ipad:" + this.size() + "," + this.face(); } }
具体产品已经设计出来了,接下来,我们就需要建立自己的工厂生产手机和pad了,首先我们抽象出一个Foxconn工厂,负责Mobile和Pad的生产,代码如下:
/** * 抽象的foxconn工厂 * User: Realfighter * Date: 2014/8/26 * Time: 12:01 */ public interface Foxconn { public Mobile produceMobile();//生产手机 public Pad producePad();//生产pad }
接下来,我们就需要对产品系列的生产进行分工,我们建立了郑州富士康和深圳富士康来进行不同系列产品的生产,郑州富士康负责生产Nokia和AndroidPad,深圳富士康负责生产Iphone和Ipad,很快我们的工厂建立起来了, 代码如下:
/** * 郑州富士康生产Nokia和AndroidPad * User: Realfighter * Date: 2014/8/26 * Time: 12:02 */ public class ZhengzhouFoxconn implements Foxconn { @Override public Mobile produceMobile() { return new Nokia(); } @Override public Pad producePad() { return new AndroidPad(); } } /** * 深圳富士康生产Iphone和IPad * User: Realfighter * Date: 2014/8/26 * Time: 12:09 */ public class ShenzhenFoxconn implements Foxconn { @Override public Mobile produceMobile() { return new Iphone(); } @Override public Pad producePad() { return new Ipad(); } }
经过一段时间的努力,我们的工厂能够正常的出货了,这时候供应商找到了我们的工厂开始拿货,代码如下:
/** * Mobile和Pad供应商 * User: Realfighter * Date: 2014/8/26 * Time: 12:22 */ public class Supplier { public static void main(String[] args) { Foxconn foxconn;//富士康 Mobile mobile;//手机 Pad pad;//平板 //首先来到郑州富士康 foxconn = new ZhengzhouFoxconn(); //拿到生产的手机 mobile = foxconn.produceMobile(); //验货 System.out.println(mobile.toString());// Nokia:3000.0 //拿到生产的pad pad = foxconn.producePad(); //验货 System.out.println(pad.toString()); // AndroidPad:10.4,better //同样的来到深圳富士康,拿到手机和pad,验货 foxconn = new ShenzhenFoxconn(); mobile = foxconn.produceMobile(); System.out.println(mobile.toString());// Iphone:5000.0 pad = foxconn.producePad(); System.out.println(pad.toString()); // Ipad:9.7,best } }
总结:抽象工厂模式是三种工厂模式形态中最为抽象和最具一般性的一种形态,从数据结构的层面来说,如果将简单工厂模式比作列,工厂方法模式就好比一颗树, 抽象工厂模式就好比一片森林。它将一系列相似的产品放在一起进行统一的创建,将具体的产品从客户代码中分离出来,使我们能够很方便的改变产品的系列,这是 它的优点,但是当我们需要在这个产品系列中创建新的产品时,就需要修改抽象工厂的接口,这也是它的缺点。