《设计模式精解》学习笔记(八)------Abstract Factory(抽象工厂)模式

《设计模式精解》学习笔记(八)------Abstract Factory(抽象工厂)模式

 

GoFAbstract Factory模式的意图是“提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类”。

 

工厂模式有: 抽象工厂(Abstract Factory)、工厂方法(Factory Method)。依照《设计模式精解》的顺序,这里先学习Abstract Factory模式。

 

工厂模式是传说中用的最广的模式了。我们通常用某个类Class来生成一个对象,例如:A a = new A();  所谓工厂就是生产某种产品的地方。那么工厂模式就是用来生成一些列产品(对象)的。有时候,几个对象需要按照相同的样式被实例化。比如说,在处理显示器显示精度的时候,有些机器能显示高清晰图像,而有些机器只能显示低分辨率图像。那么在工作上就要求系统去适配最合适的功能。Abstract Factory模式能确保系统总能根据当前的情况获得合适的对象。

 

假如我们要开发一个系统,要求提供打印驱动和显示驱动,还要求在不同配置的机器上要有合适的驱动,例如:在高配置的机器上要求精度高的驱动,在低配置的机器上要求精度低的驱动。

 

开始的解决方法这样:提供一个DisplayDriver抽象类(或者接口)然后派生出两个类Lrdd(提供低精度显示驱动)和Hrdd(提供高精度显示驱动);再提供一个PrintDriver抽象类(或者接口)然后派生出两个类Lrpd(提供低精度打印驱动)Hrpd(提供高精度打印驱动)。最后在ApControl类中分别实例化四个派生类的对象来提供相关的驱动。这样做是很合理的,但是当需求改变了,现在要求提供中等精度的驱动,或者其它要求。我们又从那两个抽象类中分别派生出若干子类。这样又出现了类爆炸的情况,我们要在ApControl类中分别实例化那些类才能提供我们所要的功能。这时我们就应该想一下用Abstract Factory模式了。先看一下Abstract Factory模式的UML图:

( )

Abstract Factory模式UML

在上图中我们可以看到,用一个工厂(ResFractory)来“生产”我们需要的“产品”(类)。我们不管有多少具体类,在Abstract Factory模式中ApControl类只使用Abstract Factory类(ResFactory类)和Abstract Product类(DisplayDriver类和PrintDriver类)的接口。通常在运行时刻创建一个具体类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。Abstract Factory将产品对象的创建延迟到它的具体子类中。

 

下面给出上图的简易代码:

先创建产品:

package Factory;

 

public abstract class DisplayDriver

{

       public abstract void dDriver();//抽象方法,使派生类能够自由实现所需的显示功能。

      

}//end abstract class DisplayDriver

 

 

package Factory;

 

public class Lrdd extends DisplayDriver

{

 

       public Lrdd()

       {

              System.out.println("低分辨率__显示驱动");

       }//end Lrdd()

      

       public void dDriver() //实现基类抽象方法

       {

              System.out.println("显示出__低分辨率图像");

       }//end dDrover()

      

}//end class Lrdd

 

 

package Factory;

 

public class Hrdd extends DisplayDriver

{

       public Hrdd()

       {

              System.out.println("高分辨率--显示驱动");

       }//end Hrdd()

 

       public void dDriver()

       {

              System.out.println("显示出--高分辨率图像");

       }//end dDriver()

 

}//end class Hrdd

 

 

package Factory;

 

public abstract class PrintDriver

{

       public abstract void pDriver();//抽象方法,使派生类能够自由实现所需的打印功能。

      

}//end abstract class PrintDriver

 

 

package Factory;

 

public class Lrpd extends PrintDriver

{

 

       public Lrpd()

       {

              System.out.println("低分辨率__打印驱动");

       }//end Lrpd()

 

       public void pDriver()

       {

              System.out.println("打印__低分辨率图像");

       }//end pDriver()

      

}//end class Lrpd

 

 

package Factory;

 

public class Hrpd extends PrintDriver

{

 

       public Hrpd()

       {

              System.out.println("高分辨率--打印驱动");

       }//end Hrpd()

 

       public void pDriver()

       {

              System.out.println("打印--高分辨率图像");

       }//end pDriver()

 

}//end class Hrpd

 

再创建工厂:

package Factory;

 

public abstract class ResFactory

{

       //抽象方法,使派生类自由实现显示功能

       abstract public DisplayDriver getDispDrvr();

      

       //抽象方法,使派生类自由实现打印功能

       abstract public PrintDriver getPrtDrvr();

}//end abstract class ResFactory

 

 

package Factory;

 

public class LowResFact extends ResFactory {

 

       public LowResFact()

       {

              System.out.println("低分辨率---->驱动");

       }//end LowResFact()

 

       public DisplayDriver getDispDrvr()

       {

              return new Lrdd();

       }//end getDispDrvr()

 

       public PrintDriver getPrtDrvr()

       {

              return new Lrpd();

       }//end getPrtDrvr()

 

}//end class LowResFact

 

 

package Factory;

 

public class HighResFact extends ResFactory

{

 

       public HighResFact()

       {

              System.out.println("高分辨率---->驱动");

       }//end HighResFact()

 

       public DisplayDriver getDispDrvr()

       {

              return new Hrdd();

       }//end getDispDrvr()

 

       public PrintDriver getPrtDrvr()

       {

              return new Hrpd();

       }//end getPrtDrvr()

 

}//end class HighResFact

 

 

利用工厂产生不同的产品:

package Factory;

 

public class ApControl

{

       private DisplayDriver lowDisplayDriver; //需要----分辨率--显示--驱动

       private PrintDriver highPrintDriver; //需要----分辨率--打印--驱动

      

       //     生产出低分辨率驱动(注:没有说明是低显示驱动还是低打印驱动)

       private ResFactory lowDriver;

      

       //     生产出高分辨率驱动(注:没有说明是高显示驱动还是高打印驱动)

       private ResFactory highDriver;

 

       public ApControl()

       {

              lowDriver = new LowResFact();//实例化低分辨率驱动对象

              highDriver = new HighResFact();//实例化高分辨率驱动对象

       }//end ApControl()

 

       public void displayDriver()

       {

              lowDisplayDriver = lowDriver.getDispDrvr();//得到低分辨率驱动

              lowDisplayDriver.dDriver();//低分辨率显示驱动

             

              highPrintDriver = highDriver.getPrtDrvr();//得到低分辨率驱动

              highPrintDriver.pDriver();//高分辨率显示驱动

       }//end displayDriver()

      

       public static void main(String[] args)

       {

              System.out.println("Abstract Factory");

              ApControl ac = new ApControl();

              ac.displayDriver();

       }//end main(...)

 

}//end class ApControl

 

输出结果如下:

Abstract Factory

低分辨率---->驱动

高分辨率---->驱动

低分辨率__显示驱动

显示出__低分辨率图像

高分辨率--打印驱动

打印--高分辨率图像

 

Abstract Factory模式适用性:

l         在以下情况可以使用Abstract Factory模式:

l         一个系统要独立于他的产品的创建、组合和表示时;

l         一个系统要由多个产品系列中的一个来配置时;

l         当你要强调一系列相关的产品对象的设计以便进行联合使用时;

l         当你提供一个产品类库,而只想显示他们的接口而不是实现时。

 

Abstract Factory模式中ApControl的责任是知道如何与合适的对象协同工作;ResFactory的责任是提供合适的对象。

 

Abstract Factory模式:关键特征

l         意图:你需要为特定的客户(或情况)提供特定系列的对象。

l         问题:一系列相关的对象需要被实例化。

l         解决方案:协调不同系列对象的创建过程。提供一种方法保持“如何在客户对象外部执行兑现实例化”的规则,客户对象将使用这些实例化出来的对象。

l         参与者与协作者:Abstract Factory为“如何创建需要的每一个系列的对象”定义接口。典型的情况下,每个系列都独立拥有自己的ConcreteFactory,通过它被实例化。

l         效果:这个模式将“使用哪些对象”的规则与“如何使用这些对象”的逻辑相隔离。

l         实现:定义一个抽象类来指定那些对象将被创建。然后为每个系列实现一个具体类。表或文件也可以被用于达到同样的目的

 

下面是Abstract Factory模式涉及的3关键策略:

1. 发现并封装变化点

       “使用哪个驱动对象”的选择食变化的。所以,将它封装在ResFactory类中。

2. 优先使用对象组合,而不是类继承

       将变化点放在一个独立的对象——ResFactory对象——中并让ApControl对象使用ResFactory对象,而不是拥有两类不同的ApControl对象。

3. 针对接口设计,而不是针对实现设计

       ApControl知道怎样想ResFactory请求实例化驱动对象——它不知道(或不关心)ResFactory对象实际如何响应这一请求。

 

参考文献:

Thinking in Patterns by Bruce Eckel

《设计模式》 by GoF

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=586034


 

你可能感兴趣的:(设计模式)