Abstract Factory(抽象工厂)模式

Abstract Factory (抽象工厂)模式

 

GoF Abstract 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 对象 实际如何响应这一请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抽象工厂模式Abstract Factory Pattern) 引入: 在前面介绍的两个创建型模式里面,我们解决的都是有关"new"的问题,用它们来避免显式指定类创建对象。我写的也非常简单易懂,相信看过的朋友们都应该对简单工厂模式工厂方法模式的意图、所能解决的问题及适用情景有一定的了解了。但是若要达到灵活运用,什么时候用,怎样用合适还不是看一篇文章就能解决的问题。呵呵..这需要你对OO的理解程度,你的项目开发经验等等许多方面的积累。一起努力喔。。 好了,咱们言归正传,过对这两个模式的了解,我们掌握一种思想,就是在创建一个对象时,需要把容易发生变化的地方给封装起来,来控制变化(哪里变化,封装哪里),以适应客户的变动,项目的扩展。但是,我们在软件系统,经常面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,这“一系列相互依赖的对象”也要改变,如何应对这种变化呢?如何像简单工厂模式工厂方法模式一样绕过常规的"new",然后提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?可能有人会说,你也可以将这些对象一个一个工厂方法模式来解决呀?但是,我们试想,既然是一系列相互依赖的对象,它们是有联系的,每个对象都这样解决,你又如何来保证他们的联系呢?举一个例子:Windows桌面主题,当你更换一个桌面主题的时候,系统的开始按钮、任务栏、菜单栏、工具栏等等都变了,而且是一起变的,他们的色调都还很一致,难道类似这样的问题,怎么来解决呢?它的天敌就是抽象工厂模式。 意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 参考者: 也就是该模式的各个类或对象之间的关系: 抽象工厂Abstract Factory) 声明生成一系列抽象产品的方法 具体工厂(Concrete Factory) 执行生成一系列抽象产品的方法,生成一系列具体的产品 抽象产品Abstract Product) 为这一系列的某一种产品声明接口 具体产品(Product) 定义具体工厂生成的具体产品的对象,实现产品接口 客户(Client) 我们的应用程序客户端(不要理解成人),使用抽象产品抽象工厂生成对象。 抽象工厂模式UML抽象工厂模式在生活的实例 咱们继续拿怎么穿衣服来说明这个抽象工厂模式。 就拿你来说吧。工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。咱们假设一种情况(现实是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在你的家,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜取出了。用OO的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。 分析: 要好好去读上面那个实例,虽然有点绕嘴,其实只要用心去读,分清了抽象工厂模式的各个角色,对理解设计模式是非常重要的。理解头绪,然后接合简单工厂模式工厂方法模式工厂家族的了解,再加上抽象工厂模式的意图,头脑差不多有一个雏型了吧。好了,咱们一起来分析一下。。 先把各个角色揪出来。 抽象工厂:虚拟的衣柜,它只是个概念而已。在项目可能是一个接口或抽象类,定义规则,取出上衣,裤子。 具体工厂:具体的存在的衣柜,它用于存放某一种成套的衣服,换句话说,这种成套的衣服都是从这个衣柜取出的。在项 目继承于抽象工厂,实现抽象工厂的方法,取出具体产品,某一件上衣,某一条裤子。 抽象产品:虚拟的衣服,也只是个概念。在项目可能是多个接口或抽象类,定义规则,有什么特性,起什么作用。 具体产品:具体的实际存在的产品,它指的就是用于组装成某一套衣服的某一件上衣或裤子。它继承自某一个抽象产品。实 现抽象产品制定的规则,特性。 它们之间怎么联系呢?客户在用的时候,依赖的又是什么呢? 客户在要的时候,首先要说出你要的什么系列的衣服,然后根据它的要求生成一个具体工厂的实例,剩下的工作就都是这个倒霉的具体工厂了,它会根据自己的实现生成一个上衣,生成一个裤子,然后把它交给客户。客户在这一过程并不知道具体工厂都做了什么。也就是说,客户只依赖于抽象工厂和抽象产品了。在初始化的时候会用到一次具体工厂类名,我们根据.NET特有的反射机制又可以把这个在客户端唯一的具体的非抽象类放到一个应用程序配置文件,防止它变化。 这就符合了设计模式的“开放--封闭”原则,依赖倒转原则,里氏代换原则等等。 具体代码如下: 抽象工厂角色: 1namespace AbstractFactory 2{ 3 //抽象工厂类, 4 public abstract class AbstractClothes 5 { 6 //抽象方法:创建一个上衣 7 abstract public AbstractCoat CreateCoat(); 8 //抽象方法:创建一个裤子 9 abstract public AbstractTrousers CreateTrousers(); 10 } 11} 12 抽象产品角色: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 抽象产品----上衣抽象类 5 /// </summary> 6 public abstract class AbstractCoat 7 { 8 //性别属性 9 public abstract bool Sex 10 { 11 get; 12 } 13 14 //样式属性 15 public abstract string Style 16 { 17 get; 18 } 19 } 20 21 /**//// <summary> 22 /// 抽象产品----裤子抽象类 23 /// </summary> 24 public abstract class AbstractTrousers 25 { 26 //性别属性 27 public abstract bool Sex 28 { 29 get; 30 } 31 32 //样式属性 33 public abstract string Style 34 { 35 get; 36 } 37 } 38} 39 具体工厂角色: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 ///时尚男装 5 /// </summary> 6 public class FashionManClothes:AbstractClothes 7 { 8 public override AbstractFactory.AbstractCoat CreateCoat() 9 { 10 return new CoatA(); 11 } 12 13 public override AbstractTrousers CreateTrousers() 14 { 15 return new TrousersA(); 16 } 17 } 18 19 /**//// <summary> 20 /// 时尚女装 21 /// </summary> 22 public class FashionWomanClothes : AbstractClothes 23 { 24 public override AbstractCoat CreateCoat() 25 { 26 return new CoatB(); 27 //throw new Exception("The method or operation is not implemented."); 28 } 29 public override AbstractTrousers CreateTrousers() 30 { 31 return new TrousersB(); 32 //throw new Exception("The method or operation is not implemented."); 33 } 34 } 35} 具体产品角色:(注意:我并没有把所有的具体产品类都列出来,由于简单,可以推想出剩余的产品类,详见附件) 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 时尚男性上衣 5 /// </summary> 6 public class CoatA:AbstractFactory.AbstractCoat 7 { 8 private bool sex = true; 9 private string style = "时尚"; 10 /**//// <summary> 11 /// 重写基类的Sex属性 12 /// </summary> 13 public override bool Sex 14 { 15 get 16 { 17 return sex; 18 } 19 } 20 21 /**//// <summary> 22 /// 重写基类的Style属性 23 /// </summary> 24 public override string Style 25 { 26 get 27 { 28 return style; 29 } 30 } 31 } 32 33 /**//// <summary> 34 /// 时尚男性裤子 35 /// </summary> 36 public class TrousersA : AbstractTrousers 37 { 38 private bool sex = true; 39 private string style = "时尚"; 40 public override bool Sex 41 { 42 get 43 { 44 return sex; 45 } 46 } 47 public override string Style 48 { 49 get 50 { 51 return style; 52 } 53 } 54 } 55} 客户端代码: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 创建衣服类 5 /// </summary> 6 public class CreateClothes 7 { 8 private AbstractCoat myCoat; 9 private AbstractTrousers myTrousers; 10 public CreateClothes(AbstractClothes clothes) 11 { 12 myCoat = clothes.CreateCoat(); 13 myTrousers = clothes.CreateTrousers(); 14 } 15 16 public void ShowMyClothes() 17 { 18 Console.WriteLine("My Clothes:"); 19 string sex= myCoat.Sex ? "男" : "女"; 20 //Console.WriteLine("Coat:{0} {1}", myCoat.Sex ? "男" : "女", myCoat.Style); 21 Console.WriteLine("Coat:{0} {1}", sex, myCoat.Style); 22 sex=myTrousers.Sex?"男":"女"; 23 Console.WriteLine("Trousers:{0} {1}", sex, myTrousers.Style); 24 } 25 } 26 27 28 public class Client 29 { 30 static void Main(string[] args) 31 { 32 //创建一个工厂类的实例 33 string assemblyName = ConfigurationManager.AppSettings["assemblyName"]; 34 string fullTypeName =string.Concat( ConfigurationManager.AppSettings["nameSpaceName"] ,".", ConfigurationManager.AppSettings["typename"]); 35 36 AbstractClothes factory = (AbstractClothes)Assembly.Load(assemblyName).CreateInstance(fullTypeName); 37 CreateClothes clothes = new CreateClothes(factory); 38 clothes.ShowMyClothes(); 39 Console.Read(); 40 } 41 } 42} 43 app.config文件 1<configuration> 2 <appSettings> 3 <!--一般情况下只需改第三个"typename"就行了,具体工厂类 --> 4 <add key="assemblyName" value="ConcreteFactory"/> 5 <add key="nameSpaceName" value="AbstractFactory"/> 6 <add key="typename" value="FashionManClothes"/> 7 </appSettings> 8</configuration>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值