设计模式(一)工厂模式Factory(创建型)

设计模式一 工厂模式Factory

         在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。

模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?

解决方案:建立一个工厂来创建对象

实现:

一、引言
    1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。
    2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。
    3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。你需要指定某个具体的工厂才能生产车出来。
    4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。而且这空调必须对应给系列车才能使用。于是这个工厂开始生产宝马车和需要的空调。
         最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.
   (我只是举个例子,说到宝马配置空调完全是为了举例,甚至有点扯,哪有车和空调必须对应才能使用啊)
     这就是工厂模式。
二、分类 
        工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 
工厂模式可以分为三类: 
1)简单工厂模式(Simple Factory) 
2)工厂方法模式(Factory Method) 
3)抽象工厂模式(Abstract Factory) 
         这三种模式从上到下逐步抽象,并且更具一般性。 
        GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。 
三、区别 
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类可以创建多个具体产品类的实例。   
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
两者皆可。 

四、简单工厂模式 
建立一个工厂(一个函数或一个类方法)来制造新的对象。
分布说明引子:从无到有。客户自己创建宝马车,然后拿来用。
 

[php] view
plain
 copy

 print?

  1. <?php  
  2. /** 
  3.  * 车子系列 
  4.  * 
  5.  */  
  6. Class BWM320{  
  7. function __construct($pa) {  
  8.   
  9. }  
  10. }  
  11. Class BMW523{  
  12.    function __construc($pb){  
  13.   
  14. }  
  15. }  
  16.   
  17. /** 
  18.  *  
  19.  * 客户自己创建宝马车 
  20.  */  
  21. class Customer {  
  22.   
  23.    function createBMW320(){  
  24.        return new BWM320();  
  25.    }  
  26.   
  27.    function createBMW523(){  
  28.        return new BMW523();  
  29.    }  
  30. }   

       客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车型号就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式

即我们建立一个工厂类方法来制造新的对象。如图:

产品类:

[php] view
plain
 copy

 print?

  1. <?php  
  2. /** 
  3.  * 车子系列 
  4.  * 
  5.  */  
  6. abstract Class BWM{  
  7.     function __construct($pa) {  
  8.   
  9.     }  
  10. }  
  11. Class BWM320 extends BWM{  
  12.     function __construct($pa) {  
  13.   
  14.     }  
  15. }  
  16. Class BMW523 extends BWM{  
  17.    function __construc($pb){  
  18.   
  19.    }  
  20. }  

 工厂类:

[php] view
plain
 copy

 print?

  1. /** 
  2.  *  
  3.  * 工厂创建车 
  4.  */  
  5. class Factory {  
  6.   
  7.   
  8.     static function  createBMW($type){  
  9.         switch ($type) {  
  10.           case 320:  
  11.              return new BWM320();  
  12.           case 523:  
  13.              return new BMW523();  
  14.         //....  
  15.    }  
  16. }  

客户类:

[php] view
plain
 copy

 print?

  1. /** 
  2.  *  
  3.  * 客户通过工厂获取车 
  4.  */  
  5. class Customer {  
  6.     private $BMW;  
  7.     function getBMW($type){  
  8.         $this¬-> BMW =  Factory::createBMW($type);  
  9.     }  
  10. }  

      简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。 
      先来看看它的组成: 
         1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
         2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。         
         3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 
        
        下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW($type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类
或者上帝类。 
        我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员:( 
        于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。
五、工厂方法模式 
        工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 
工厂方法模式组成: 
       1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 
       2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 
       3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 
       4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 
       工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的! 
 


代码如下: 

产品类:

[php] view
plain
 copy

 print?

  1. <?php  
  2. /** 
  3.  * 车子系列 
  4.  * 
  5.  */  
  6. abstract Class BWM{  
  7. function __construct($pa) {  
  8.   
  9. }  
  10. }  
  11. Class BWM320 extends BWM{  
  12. function __construct($pa) {  
  13.   
  14. }  
  15. }  
  16. Class BMW523 extends BWM{  
  17.    function __construc($pb){  
  18.   
  19. }  
  20. }  

创建工厂类:

[php] view
plain
 copy

 print?

  1. /** 
  2.  * 创建工厂的接口 
  3.  * 
  4.  */  
  5. interface FactoryBMW {   
  6.        function createBMW();   
  7. }   
  8.   
  9.   
  10. /** 
  11.  *  
  12.  * 创建BWM320车 
  13.  */  
  14. class FactoryBWM320 implements FactoryBMW {  
  15.    function  createBMW($type){  
  16.       return new BWM320();  
  17.    }  
  18.   
  19. }  
  20.   
  21.   
  22. /** 
  23.  *  
  24.  * 创建BWM523车 
  25.  */  
  26. class FactoryBWM523 implements FactoryBMW {  
  27.    function  createBMW($type){  
  28.       return new BMW523();  
  29.    }  
  30. }  

客户类:

[php] view
plain
 copy

 print?

  1. /** 
  2.  *  
  3.  * 客户得到车 
  4.  */  
  5. class Customer {  
  6.    private $BMW;  
  7.    function  getBMW($type){  
  8.       switch ($type) {  
  9.         case 320:  
  10.            $BWM320 = new FactoryBWM320();  
  11.            return $BWM320->createBMW();  
  12.         case 523:  
  13.            $BWM523 = new FactoryBWM523();  
  14.            return $BWM320->createBMW();  
  15.             //....  
  16.       }  
  17.   
  18.   }  
  19. }  

       可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情 况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实 现。

工厂方法小结: 
        工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式: 
     1)当客户程序不需要知道要使用对象的创建过程。 
     2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

       简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判 断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。
       面对这种情况,我们可以使用反射机制:

[php] view
plain
 copy

 print?

  1.  class Customer {  
  2.      private $BMW;  
  3.      function  getBMW($type){  
  4.          $class = new ReflectionClass('FactoryBWM' .$type );//建立 'FactoryBWM'这个类的反射类    
  5.           $instance  = $class->newInstanceArgs();//相当于实例化'FactoryBWM' .$type类    
  6.           return $instance->createBMW();  
  7.         //或者直接   
  8.          /** 
  9.          * $instance = new 'FactoryBWM' .$type(); 
  10.          * return $instance->createBMW(); 
  11.          */  
  12.     }  
  13. }  

 

六、抽象工厂模式 
       随着客户的要求越来越高,宝马车需要配置空调。于是这个工厂开始生产宝马车和配置需要的空调。这时候工厂有二个系列的产品:宝马车和空调.宝马车必须使用对应的空调才能使用.这时候分别使用一个车工厂和一个空调工厂都不能满足我们的需求,我们必须确认车跟空调的对应关系。因此把车工厂跟空调工厂联系在一起。因此出现了抽象工厂模式。
     可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。 
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件:
     1)系统中有多个产品族,而系统一次只可能消费其中一族产品。 
     2)同属于同一个产品族的产品以其使用。 
抽象工厂模式的各个角色(和工厂方法一样): 
     1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 
     2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
     3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。
     4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。

 

其结构:

 
我们的例子:
 

代码:

产品类:

[php] view
plain
 copy

 print?

  1. <?php  
  2. /** 
  3.  * 车子系列以及型号 
  4.  * 
  5.  */  
  6. abstract class  BWM{  
  7. }  
  8.   
  9. class BWM523 extends  BWM {  
  10. }  
  11. class BWM320 extends  BWM {  
  12.   
  13.   
  14. }  
  15. /** 
  16.  * 空调 
  17.  * 
  18.  */  
  19. abstract class aircondition{  
  20. }  
  21. class airconditionBWM320  extends aircondition {  
  22.   
  23. }  
  24. class airconditionBWM52 extends aircondition {  
  25.   
  26. }  

创建工厂类:

[php] view
plain
 copy

 print?

  1. /** 
  2.  * 创建工厂的接口 
  3.  * 
  4.  */  
  5. interface FactoryBMW {   
  6.      function createBMW();   
  7.      function createAirC();   
  8. }   
  9.   
  10.   
  11. /** 
  12.  *  
  13.  * 创建BWM320车 
  14.  */  
  15. class FactoryBWM320 implements FactoryBMW {  
  16.     function  createBMW(){  
  17.     return new BWM320();  
  18. }  
  19. function  createAirC(){ //空调  
  20.     return new airconditionBWM320();  
  21. }  
  22. }  
  23.   
  24.   
  25. /** 
  26.  *  
  27.  * 创建BWM523车 
  28.  */  
  29. class FactoryBWM523 implements FactoryBMW {  
  30.     function  createBMW(){  
  31.     return new BWM523();  
  32. }  
  33. function  createAirC(){  
  34.     return new airconditionBWM523();  
  35. }  
  36. }  

客户:

[php] view
plain
 copy

 print?

  1. /** 
  2.  *  
  3.  * 客户得到车 
  4.  */  
  5. class Customer {  
  6.    private $BMW;  
  7.    private $airC;  
  8.    function  getBMW($type){  
  9.        $class = new ReflectionClass('FactoryBWM' .$type );//建立 Person这个类的反射类    
  10.         $instance  = $class->newInstanceArgs();//相当于实例化Person 类    
  11.         $this->BMW =  $instance->createBMW();  
  12.        $this->airC =  $instance->createAirC();  
  13.    }  
  14. }  
时间: 2024-07-30 07:57:02

设计模式(一)工厂模式Factory(创建型)的相关文章

JAVA:将反射技术应用于工厂模式(Factory)和单例模式(Singleton)的简单代码

反射技术大量用于Java设计模式和框架技术,最常见的设计模式就是工厂模式(Factory)和单例模式(Singleton). 参考URL: http://blog.csdn.net/xiaohai798/article/details/11640427 用接口来沟通不同程序的开发进度,不必等上游程序写好代码之后,再注入后面流程的程序员.且在实现上,可以用配置文件灵活变更,而不用重编译整个项目. InterfaceTest.java: interface InterfaceTest { //基于接

解读设计模式----抽象工厂模式(AbstractFactory Pattern)

一.模式描述 我的程序中有需要一系列的对象,比如我们要吃一碗米饭(Rice),要喝一杯咖啡(Coffee)......,要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活.那么我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象呢? 这当然是可以的,根据GOF在<设计模式>一书里介绍,要创建对象这样的工作应该是属于创建型模式完成的.熟悉各种设计模式意图的朋友就会很快得

深入理解JavaScript系列(28):设计模式之工厂模式详解

 这篇文章主要介绍了深入理解JavaScript系列(28):设计模式之工厂模式详解,工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类,需要的朋友可以参考下     介绍 与创建型模式类似,工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类. 工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类.该模式使一个类的实例化延迟到了子类.而子类可以重写接口方法以便创建的时候指定自己的对象类型. 这个模式十分有用,尤其是创建对象的流程赋值的时候,比如依赖于

PHP设计模式之工厂模式与单例模式_php技巧

本文实例讲述了PHP设计模式之工厂模式与单例模式实现方法.分享给大家供大家参考,具体如下: 设计模式简单说应对某类问题而设计的解决方式 工厂模式:应对需求创建相应的对象 class factory{ function __construct($name){ if(file_exists('./'.$name.'.class.php')){ return new $name; }else{ die('not exist'); } } } 单例模式:只创建一个对象的实例,不允许再创建实例,节约资源(

.NET设计模式(7):创建型模式专题总结(Creational Pattern)

概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模式. 为什么需要创建型模式 所有的创建型模式都有两个永恒的主旋律:第一,它们都将系统使用哪些具体类的信息封装起来:第二,它们隐藏了这些类的实例是如何被创建和组织的.外界对于这些对象只知道它们共同的接口,而不清楚其具体的实现细节.正因如此,创建型模式在创建什么(what),由谁(who)来创建,以及何

.NET设计模式-抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory) --探索设计模式系列之三 Terrylee,2005年12月12日 概述 在软件系统中,经常面临着"一系列相互依赖的对象"的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种"封装机制"来避免客户程序和这种"多系列具体对象创建工作"的紧耦合?这就是我们要说的抽象工厂模式. 意图 提供一个创建一系列相关或相互依赖对象的接

Java设计模式之工厂模式(Factory模式)介绍_java

工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量. 我们以类Sample为例,

解读设计模式----简单工厂模式(SimpleFactory Pattern)

一.模式概述 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,学习了此模式可以为后面的很多中模式打下基础.那好,我们就来了解下什么是简单工厂模式? 我们来分析一个现实生活中的案例,每天早晨起床洗唰后是干什么呢?吃早餐(这里只针对在外吃早餐的上班族

面向对象编程设计模式--简单工厂模式讲解

工作之余,在看资料过程中发现一个极易理解的简单工厂模式的例子,自己亲自试练一番,感觉对这个设计模式不熟悉的朋友, 一看马上就知道是什么回事了. 简单工厂模式根据提供给它的数据,返回几个可能类中的一个类的实例.通常它返的类都有一个共同的你类和共同的方法, 但每个方法执行的任务不同,而且根据不同的数据进行了优化. 简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一. 下面进行一个代码示例: public class g