Chinaunix首页 | 论坛 | 博客
  • 博客访问: 544259
  • 博文数量: 151
  • 博客积分: 7010
  • 博客等级: 少将
  • 技术积分: 1405
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-22 14:32
文章分类

全部博文(151)

文章存档

2011年(1)

2010年(23)

2009年(1)

2008年(126)

我的朋友

分类: Java

2010-01-06 14:08:40

一、Factory是什么的工厂?
    Factory 是类的工厂,是集中创建类对象的地方.
 
二、为何使用?
    为什么说工厂模式是最常用,因为工厂模式就相当于创建对象的new. 工厂模式就是用来创建对象的.
    比如我们有一个类Sample 我们要创建Sample 的对象:
       Sample sample=new Sample();
    如果我们要在创建sample 之前做点事情,比如,赋值等,可以使用Sample 的构造函数:
       Sample sample=new Sample(参数);
    如果创建sample 时做的事情不是如赋值这样简单的事,可能是很长一段代码,如果也写入构
    造函数中,那明显的就违背了面向对象的原则.封装(Encapsulation)和分派(Delegation);
    我们需要将创建实例的责任与使用实例的责任分开, 使得语句
       Sample sample=new Sample(参数);
   
    就是简单的责任:使用Sample 这个实例;至于创建Sample的任务就交给了Factory工厂模式.
    还有,如果Sample 有个继承如MySample, 按照面向接口编程,我们需要将Sample 抽象成一个接口.
    现在Sample 是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:
       Sample mysample=new MySample();
       Sample hissample=new HisSample();

    随着项目的深入,Sample 可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.你会建立一个专门生产Sample 实例的工厂:
       public class Factory{
         public static Sample creator(){
         ....
         if (which==1)
           return new MySample();
         else if (which==2)
           return new HisSample();
         }
       }
    那么在你的程序中,如果要实例化MySample 时.就使用
    Sample sample=Factory.creator();
    这样,在整个就不涉及到Sample 的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.
 
注:我们不妨考虑一下,如果在项目进行中,我们需要从Sample派生出几个子类,但我们不用Factory模式,我们可以怎么做?就象上面MySample,HisSample的实例化一样,我们可以采用多态模式,这样每个需要用到MySample和HisSample对象的地方,我们都需要针对性的创建他们的实例。当需求变动需要再从Sample派生出HerSample、TheirSample等子类的时候,我们需要分别修改所有创建Sample实例的地方,以便他们能够创建出HerSample和TheirSample的实例,这样需要修改大量的代码。而一旦采用Factory模式,所有创建类对象的地方都采用同一种方法,即从Factory的方法中生成,这样,不论Sample今后派生了多少个子类,那么需要修改的地方只是创建新的子类和修改Factory里的方法,其他地方都不用修改,这就大大减轻了代码的维护量,这也是Factory的精髓所在。
 
 
三、如何使用?
    工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).
    上例中,我们使用的是简单的工厂方法. 这两个模式没有很明显的区别,区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,我们就可能要将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现:
    public abstract class Factory{
       public abstract Sample creator();
       public abstract Sample2 creator();
    }
   
    public class SimpleFactory extends Factory{
       public Sample creator(){
       ......
       }   
      
       public Sample2 creator(){
       ......
       }
    }
   
    public class BombFactory extends Factory{
       public Sample creator(){
       ......
       }
      
       public Sample2 creator(){
       ......
       }
    }
 
   上例中我们只有一类产品接口 Sample , 工厂方法和抽象工厂可以创建多个产品接口的实例,比如Sample2 Sample3
   FactoryMethod 往往只是创建单个的实例。Abstract Factory 创建一系列的实例组,这些实例彼此相关。

四、工厂方法
   
  你会建立一个专门生产Sample实例的工厂:
  
  public class Factory{
  
    public static Sample creator(int which){
  
    //getClass 产生Sample 一般可使用动态类装载装入类。
    if (which==1)
      return new SampleA();
    else if (which==2)
      return new SampleB();
  
    }
  
  }
  
  
  那么在你的程序中,如果要实例化Sample时.就使用
  
  Sample sampleA=Factory.creator(1);
  
  这样,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵.
  
  使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类,用来生成产品Sample

五、抽象工厂
   工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).
   
   这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.
   
   这里假设:Sample有两个concrete类SampleA和SamleB,而Sample2也有两个concrete类Sample2A和SampleB2
   
   那么,我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现,下面就是将上例中的Factory拓展成抽象工厂:
   
   public abstract class Factory{
   
     public abstract Sample creator();
   
     public abstract Sample2 creator(String name);
   
   }
   
   public class SimpleFactory extends Factory{
   
     public Sample creator(){
       .........
       return new SampleA
     }
   
     public Sample2 creator(String name){
       .........
       return new Sample2A
     }
   
   }
   
   public class BombFactory extends Factory{
   
     public Sample creator(){
       ......
       return new SampleB
     }
   
     public Sample2 creator(String name){
       ......
       return new Sample2B
     }
   
   }
     
       
   从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产Sample和Sample2?
   
   抽象工厂还有另外一个关键要点,是因为 SimpleFactory内,生产Sample和生产Sample2的方法之间有一定联系,所以才要将这两个方法捆绑在一个类中,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以名称叫SimpleFactory。
   
   
   在实际应用中,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用。

六、工厂方法和抽象工厂的区别
   工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象)。而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。

阅读(599) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~