java工厂模式_Java中的模式 --工厂模式

工厂模式主要负责将大量有共通接口的类实例化,工场模式有以下几种形态

简单工厂(Simple Factory)   又称 静态工厂方法(Static Factory Method)

工厂方法(Factory Method)   又称 多态性工厂(Polymorphic Factory)

抽象工厂(Abstract Factory) 又称 工具箱(Kit or Toolkit)

先说简单工厂模式:

需求:一个水果工厂,为任何来的客人提供水果,现有水果Apple ,Banana,Orange

实现:

定义三个类Apple,Banana,Orange 让他们都实现Fruit接口

4f1150b881333f12a311ae9ef34da474.png ----------------------- list 1 -------------------------------- 1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublic class FruitFactory 9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public static Fruit factory(String which) 9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif if (which.equalsIgnoreCase( " apple " ) 9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png             returnnewApple();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  } else if (which equalsIgnoreCase( " banana " )) 9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png             returnnewBanana();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  } else if (which equalsIgnoreCase( " orange " )) 9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png             returnnewOrange();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  } else 9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png throw RuntimeException( " no this fruit " );

ecedf933ec37d714bd4c2545da43add2.png  }ecedf933ec37d714bd4c2545da43add2.png }8f1ba5b45633e9678d1db480c16cae3f.png}4f1150b881333f12a311ae9ef34da474.png----------------------- list 1 -------------------------------- 4f1150b881333f12a311ae9ef34da474.png

客人的需求实现

1

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gif try 9b8a8a44dd1c74ae49c20a7cd451974e.png{2 d18c02628675d0a2c816449d98bda930.png FruitFactory.factory( " apple " );3 d18c02628675d0a2c816449d98bda930.png FruitFactory.factory( " banana " );4 d18c02628675d0a2c816449d98bda930.png FruitFactory.factory( " orange " );5 1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gif}catch (Exception e) 9b8a8a44dd1c74ae49c20a7cd451974e.png{6 d18c02628675d0a2c816449d98bda930.png 

9b8a8a44dd1c74ae49c20a7cd451974e.png

9b8a8a44dd1c74ae49c20a7cd451974e.png7 8f1ba5b45633e9678d1db480c16cae3f.png}8 4f1150b881333f12a311ae9ef34da474.png

优点:分开了生产者和消费者的责任

缺点:所有的产品都出自一个工厂

造成问题:

1,当这个工厂出现问题时,损失惨重,不利于分散风险

2,当出现不同种类的水果(有不同接口的水果),工场内部既须要判断种类,又须要判断具体的产品。

比如这种结构:

1,水果接口Fruit

2,两个种类水果实现了Fruit接口   有籽水果 /无籽水果

3,所有有籽水果继承自有籽水果类   ,所有无籽水果继承自无籽水果类

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

1

4f1150b881333f12a311ae9ef34da474.png ----------------------- list 2 -------------------------------- 2 1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublic class FruitFactory 9b8a8a44dd1c74ae49c20a7cd451974e.png{3 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public static Fruit factory(String which, boolean hasSeed ) 9b8a8a44dd1c74ae49c20a7cd451974e.png{4 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif if (hasSeed) 9b8a8a44dd1c74ae49c20a7cd451974e.png{5 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif if (which.equalsIgnoreCase( " watermelon " ) 9b8a8a44dd1c74ae49c20a7cd451974e.png{6 d18c02628675d0a2c816449d98bda930.png return new WatermelonOne();7 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif   }else if (which equalsIgnoreCase( " orange " )) 9b8a8a44dd1c74ae49c20a7cd451974e.png{8 d18c02628675d0a2c816449d98bda930.png return new OrangeOne();9 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif else 9b8a8a44dd1c74ae49c20a7cd451974e.png{10 d18c02628675d0a2c816449d98bda930.png throw RuntimeException( " no this fruit " );11 ecedf933ec37d714bd4c2545da43add2.png   }12 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  }else 9b8a8a44dd1c74ae49c20a7cd451974e.png{13 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif if (which.equalsIgnoreCase( " watermelon " ) 9b8a8a44dd1c74ae49c20a7cd451974e.png{14 d18c02628675d0a2c816449d98bda930.png return new WatermelonTwo();15 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif   }else if (which equalsIgnoreCase( " orange " )) 9b8a8a44dd1c74ae49c20a7cd451974e.png{16 d18c02628675d0a2c816449d98bda930.png return new OrangeTwo();17 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif else 9b8a8a44dd1c74ae49c20a7cd451974e.png{18 d18c02628675d0a2c816449d98bda930.png throw RuntimeException( " no this fruit " );19 ecedf933ec37d714bd4c2545da43add2.png   }20 ecedf933ec37d714bd4c2545da43add2.png  }21 ecedf933ec37d714bd4c2545da43add2.png }22 ecedf933ec37d714bd4c2545da43add2.png}23 d18c02628675d0a2c816449d98bda930.png----------------------- list 2 -------------------------------- 24 d18c02628675d0a2c816449d98bda930.png

接着试想一下,我有20个大分类,复杂的层次结构,那么这个工厂模式怎么维护。

总结一下:简单工厂方法,在一定程度上支持了开闭原则,当增加一种水果的时候符合开闭原则

但当增加一类水果(多种有共通特点的水果)时候,出现维护困难的问题。

这个时候引入工厂方法,工厂方法利用继承,解决了上边的问题。看看它是如何解决的。

简单来说:工厂方法就是为没一大类水果实现一个"简单工厂",这些"简单工厂"都实现一个共通的接口。

这样当然就解决了问题,添加一个大类的话,就添加一个简单工厂

在我们的日常生活中经常会遇到这样的情况,如要生产IBM-PC或者Apple ,每一台计算计又有Cpu和内存

IBM-PC Apple,Cpu 内存Ram 不是一类东西,这个时候如果简单的建立四个工厂类是不对的。解决办法:

1

4f1150b881333f12a311ae9ef34da474.png ----------------------- list 3 -------------------------------- 2 1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublic IbmPcFactory 9b8a8a44dd1c74ae49c20a7cd451974e.png{3 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public Cpu CpuFactory(String cpuType) 9b8a8a44dd1c74ae49c20a7cd451974e.png{4 d18c02628675d0a2c816449d98bda930.png return new IbmPcCpu(cpuType);5 ecedf933ec37d714bd4c2545da43add2.png }6 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public Ram RamFactory(String ramType) 9b8a8a44dd1c74ae49c20a7cd451974e.png{7 d18c02628675d0a2c816449d98bda930.png return new IbmPcRam(ramType);8 ecedf933ec37d714bd4c2545da43add2.png }9 8f1ba5b45633e9678d1db480c16cae3f.png}10 1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublic AppleFactory() 9b8a8a44dd1c74ae49c20a7cd451974e.png{11 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public Cpu CpuFactory(String cpuType) 9b8a8a44dd1c74ae49c20a7cd451974e.png{12 d18c02628675d0a2c816449d98bda930.png return new AppleCpu(cpuType);13 ecedf933ec37d714bd4c2545da43add2.png }14 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public Ram RamFactory(String ramType) 9b8a8a44dd1c74ae49c20a7cd451974e.png{15 d18c02628675d0a2c816449d98bda930.png return new AppleRam(ramType);16 ecedf933ec37d714bd4c2545da43add2.png }17 8f1ba5b45633e9678d1db480c16cae3f.png}18 4f1150b881333f12a311ae9ef34da474.png----------------------- list 3 -------------------------------- 19 4f1150b881333f12a311ae9ef34da474.png

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

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

1,话说女娲造人,开始用手捏,感觉太慢

2,所以女娲想出了办法,用一条绳子(简单工厂,告诉绳子怎么造人),放到泥堆里边,然後一抖,就出来一批人

(简单工厂须要一个接口,interface 人)

3,接着女娲想要男人和女人之分,所以造了两条绳子,阳绳和阴绳(工厂方法,两个工厂,告诉阳绳怎么造男人,

女绳怎么造女人),然後一下出来一批男人,一批女人

(工厂方法须要多个接口,interface 人  interface 绳  阳绳-阴绳实现绳 男人-女人实现人)

4,可女娲还想造点动物,而且动物也想分男女(其实应改是雌雄),那怎么办,改造两条绳子,让绳子也学会怎么

造动物(抽象工厂),这个时候抖一下绳子,阳绳出来的东西,长的像人的是男人,长的像动物的是雄动物,

(抽象工厂须要再多的接口 interface 人 interface 兽 interface 绳

阳绳-阴绳实现绳 男人-女人实现人 雌动物-雄动物实现兽)

阴绳出来的东西,长的像人的是女人,长的像动物的是雌动物

最后再回到实现上,看到在list 1中,出现了大量的

if(which.equalsIgnoreCase("xxx"){

return new Xxx();

}

试想如果产品上千,上万呢。那这个将是不可想想的。Java的动态load正好解决了这个问题

看看实现

1

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gif public class FruitFactory 9b8a8a44dd1c74ae49c20a7cd451974e.png{2 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif public static Fruit factory(String which) 9b8a8a44dd1c74ae49c20a7cd451974e.png{3 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif try 9b8a8a44dd1c74ae49c20a7cd451974e.png{4 d18c02628675d0a2c816449d98bda930.png   Class clazz = Class.forName(which);5 d18c02628675d0a2c816449d98bda930.png return (Fruit)clazz.newInstance();6 97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif  }catch (Exception e) 9b8a8a44dd1c74ae49c20a7cd451974e.png{7 d18c02628675d0a2c816449d98bda930.png   

9b8a8a44dd1c74ae49c20a7cd451974e.png

9b8a8a44dd1c74ae49c20a7cd451974e.png8 ecedf933ec37d714bd4c2545da43add2.png  }9 ecedf933ec37d714bd4c2545da43add2.png }10 8f1ba5b45633e9678d1db480c16cae3f.png}11 4f1150b881333f12a311ae9ef34da474.png

好了,这个时候无论增加多少类的产品都不是问题了,你只要让所有的产品实现Fruit接口,同时为每个产品

编写自己的类。完全符合开闭原则。

posted on 2006-11-07 15:02 dreamstone 阅读(3295) 评论(3)  编辑  收藏 所属分类: 设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值