`
BlogDown
  • 浏览: 213725 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Java中的模式 --工厂模式

阅读更多


工厂模式主要负责将大量有共通接口的类实例化,工场模式有以下几种形态
简单工厂(Simple Factory)   又称 静态工厂方法(Static Factory Method)
工厂方法(Factory Method)   又称 多态性工厂(Polymorphic Factory)
抽象工厂(Abstract Factory) 又称 工具箱(Kit or Toolkit)

先说简单工厂模式:
需求:一个水果工厂,为任何来的客人提供水果,现有水果Apple ,Banana,Orange
实现:
定义三个类Apple,Banana,Orange 让他们都实现Fruit接口

----------------------- list  1 --------------------------------
public   class  FruitFactory {
  public   static  Fruit factory(String which) {
   if (which.equalsIgnoreCase( " apple " ) {
                return new Apple();
  } else   if (which equalsIgnoreCase( " banana " )) {
                return new Banana();
  } else   if (which equalsIgnoreCase( " orange " )) {
                return new Orange();
  } else {
                throw  RuntimeException( " no this fruit " );
  }
}
}
----------------------- list  1 --------------------------------


客人的需求实现

1  try {
2  FruitFactory.factory( " apple " );
3  FruitFactory.factory( " banana " );
4  FruitFactory.factory( " orange " );
5  } catch (Exception e) {

7 }
8

优点:分开了生产者和消费者的责任
缺点:所有的产品都出自一个工厂
造成问题:
1,当这个工厂出现问题时,损失惨重,不利于分散风险
2,当出现不同种类的水果(有不同接口的水果),工场内部既须要判断种类,又须要判断具体的产品。
比如这种结构:
1,水果接口Fruit
2,两个种类水果实现了Fruit接口   有籽水果 /无籽水果
3,所有有籽水果继承自有籽水果类   ,所有无籽水果继承自无籽水果类

这事如果客户要有籽西瓜,无籽西瓜 工厂类的实现

1  ----------------------- list  2 --------------------------------
2  public   class  FruitFactory {
3    public   static  Fruit factory(String which, boolean  hasSeed ) {
4     if (hasSeed) {
5      if (which.equalsIgnoreCase( " watermelon  " ) {
6      return   new  WatermelonOne();
7     } else   if (which equalsIgnoreCase( " orange " )) {
8      return   new  OrangeOne();
9      else {
10      throw  RuntimeException( " no this fruit " );
11    }
12    } else {
13      if (which.equalsIgnoreCase( " watermelon  " ) {
14      return   new  WatermelonTwo();
15     } else   if (which equalsIgnoreCase( " orange " )) {
16      return   new  OrangeTwo();
17      else {
18      throw  RuntimeException( " no this fruit " );
19    }
20   }
21  }
22 }
23  ----------------------- list  2 --------------------------------
24

接着试想一下,我有20个大分类,复杂的层次结构,那么这个工厂模式怎么维护。
总结一下:简单工厂方法,在一定程度上支持了开闭原则,当增加一种水果的时候符合开闭原则
  但当增加一类水果(多种有共通特点的水果)时候,出现维护困难的问题。
 
这个时候引入工厂方法,工厂方法利用继承,解决了上边的问题。看看它是如何解决的。
简单来说:工厂方法就是为没一大类水果实现一个"简单工厂",这些"简单工厂"都实现一个共通的接口。
这样当然就解决了问题,添加一个大类的话,就添加一个简单工厂

在我们的日常生活中经常会遇到这样的情况,如要生产IBM-PC或者Apple ,每一台计算计又有Cpu和内存
IBM-PC Apple,Cpu 内存Ram 不是一类东西,这个时候如果简单的建立四个工厂类是不对的。解决办法:

1  ----------------------- list  3 --------------------------------
2  public  IbmPcFactory {
3    public  Cpu CpuFactory(String cpuType) {
4    return   new  IbmPcCpu(cpuType);
5  }
6    public  Ram RamFactory(String ramType) {
7    return   new  IbmPcRam(ramType);
8  }
9 }
10  public  AppleFactory() {
11    public  Cpu CpuFactory(String cpuType) {
12    return   new  AppleCpu(cpuType);
13  }
14    public  Ram RamFactory(String ramType) {
15    return   new  AppleRam(ramType);
16  }
17 }
18  ----------------------- list  3 --------------------------------
19

这个就使抽象工厂了,不过抽象工厂对开闭原则的支持不够好,只在机型的增加上支持开闭,在配件上就不行了。

对比三个工厂模式,<<Java与模式>>的作者的比喻更能让人明白问题。

1,话说女娲造人,开始用手捏,感觉太慢
2,所以女娲想出了办法,用一条绳子(简单工厂,告诉绳子怎么造人),放到泥堆里边,然後一抖,就出来一批人
(简单工厂须要一个接口,interface 人)
3,接着女娲想要男人和女人之分,所以造了两条绳子,阳绳和阴绳(工厂方法,两个工厂,告诉阳绳怎么造男人,
女绳怎么造女人),然後一下出来一批男人,一批女人
(工厂方法须要多个接口,interface 人  interface 绳  阳绳-阴绳实现绳 男人-女人实现人)
4,可女娲还想造点动物,而且动物也想分男女(其实应改是雌雄),那怎么办,改造两条绳子,让绳子也学会怎么
造动物(抽象工厂),这个时候抖一下绳子,阳绳出来的东西,长的像人的是男人,长的像动物的是雄动物,
(抽象工厂须要再多的接口 interface 人 interface 兽 interface 绳
阳绳-阴绳实现绳 男人-女人实现人 雌动物-雄动物实现兽)
阴绳出来的东西,长的像人的是女人,长的像动物的是雌动物

最后再回到实现上,看到在list 1中,出现了大量的
if(which.equalsIgnoreCase("xxx"){
   return new Xxx();
}
试想如果产品上千,上万呢。那这个将是不可想想的。Java的动态load正好解决了这个问题
看看实现

1  public   class  FruitFactory {
2    public   static  Fruit factory(String which) {
3     try {
4    Class clazz  =  Class.forName(which);
5     return  (Fruit)clazz.newInstance();
6    } catch (Exception e) {
7   
8   }
9  }
10 }
11

好了,这个时候无论增加多少类的产品都不是问题了,你只要让所有的产品实现Fruit接口,同时为每个产品
编写自己的类。完全符合开闭原则。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics