《Java设计模式之工厂模式(Factory)4473.docx》由会员分享,可在线阅读,更多相关《Java设计模式之工厂模式(Factory)4473.docx(12页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Java设计模式之工厂模式(Factory) 时间:20009-008-044 17:23来源源:未知作作者:和水水柔石 CSDN IE QQ 百度 我挖 Googgle POCOO Yahooo 新浪 365KKey 天极 和讯 博拉 Livee 奇客 鲜果 收客 饭否 叽歪 挖客 核心提示:作者:和和水柔石 一、引子子 话说十十年前,有有一个爆发发户,他家家有三辆汽汽车(Beenz (奔奔驰)、BBmw (宝宝马)、AAudi (奥迪)看看来这人比比较爱国,没没有日本车车),还雇雇了司机为为他开车。不不过,爆发发户坐车时时总是这样样:上Beenz 车车后跟司机机说 开奔奔驰车! ,坐上BB
2、mw 后后他说 开开 作者:和水水柔石 一、引子话话说十年前前,有一个个爆发户,他他家有三辆辆汽车(BBenz (奔驰)、BBmw (宝宝马)、AAudi (奥迪)看看来这人比比较爱国,没没有日本车车),还雇雇了司机为为他开车。不不过,爆发发户坐车时时总是这样样:上Beenz 车车后跟司机机说 开开奔驰车! ,坐坐上Bmww 后他说说 开宝宝马车! ,坐上上Audii 后他说说 开奥奥迪车! 。 你你一定说:这人有病病!直接说说开车不就就行了?! 而当把把这个爆发发户的行为为放到我们们程序语言言中来,我我们发现CC 语言一一直是通过过这种方式式来坐车的的! 幸运运的是,这这种有病的的现象在OO
3、O 语言言中可以避避免了。下下面以Jaava 语语言为基础础来引入我我们本文的的主题:工工厂模式! 二、简介工工厂模式主主要是为创创建对象提提供了接口口。工厂模模式按照JJava 与模式中中的提法分分为三类:1. 简简单工厂模模式(Siimplee Facctoryy) 2. 工厂方方法模式(Facttory Methhod) 3. 抽抽象工厂模模式(Abbstraact FFactoory) 这三种模模式从上到到下逐步抽抽象,并且且更具一般般性。还有有一种分类类法,就是是将简单工工厂模式看看为工厂方方法模式的的一种特例例,两个归归为一类。下下面是使用用工厂模式式的两种情情况:1. 在编码码时
4、不能预预见需要创创建哪种类类的实例。2. 系统不应依赖于产品类实例如何被创建、组合和表达的细节 三、简单工工厂模式顾顾名思义,这这个模式本本身很简单单,而且使使用在业务务较简单的的情况下。它由三种角色组成(关系见下面的类图):1、工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java 中它往往由一个具体类实现。 2、抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java 中由接口或者抽象类来实现。 3、具体产品角色:工厂类所创建的对象就是此角色的实例。在java 中由一个具体类实现。那么简简单工厂模模式怎么用用呢?我来来举个例子子吧,我想想这个比讲讲一大段理理论上的
5、文文字描述要要容易理解解的多!下下面就来给给那个暴发发户治病: P 在在使用了简简单工厂模模式后,现现在暴发户户只需要坐坐在车里对对司机说句句: 开开车 就就可以了。来来看看怎么么实现的:1. /抽象象产品角色色 2. publiicinteerfacceCaar 3. publiicvoidddriive(); 4. 5. /具体体产品角色色 6. publiicclasssBeenziimpleementtsCaar 7. publiicvoidddriive() 8. Systeem.ouut.prrintlln(DDriviingBBenz); 9. 10. 11. 12. publi
6、icclasssBmmwimmplemmentssCarr 13. publiicvoidddriive() 14. Systeem.ouut.prrintlln(DDriviingBBmw); 15. 16. 。(奥奥迪我就不不写了:PP ) 1. /工厂厂类角色 2. publiicclasssDrriverr 3. 4. /工厂厂方法 5. /注意意返回类类型为抽象象产品角色色 6. publiicstatticCCarddriveerCarr(Strrings)thhrowssExcceptiion 7. 8. /判断断逻辑,返返回具体的的产品角色色给Cliient 9. if(s.e
7、quaalsIggnoreeCasee(Beenz)reeturnnnewBBenz(); 10. elseif(s.equaalsIggnoreeCasee(Bmmw) 11. returrnnewBBmw(); 12. 13. . 14. elsethroownewEExcepptionn(); 15. 。 16. 17. /欢迎迎暴发户出出场. 18. publiicclasssMaagnatte 19. publiicstatticvoiddmaiin(Sttringgaargs) 20. try 21. /告诉诉司机我今今天坐奔驰驰 22. Carccar=Driiver.drivv
8、erCaar(bbenz); 23. /下命命令:开车车 24. car.ddrivee(); 25. 。 如果将所有有的类放在在一个文件件中,请不不要忘记只只能有一个个类被声明明为pubblic 。 程序序中类之间间的关系如如下:这便是简单单工厂模式式了。下面面是其好处处: 首先先,使用了了简单工厂厂模式后,我我们的程序序不在 有病 ,更加符符合现实中中的情况;而且客户户端免除了了直接创建建产品对象象的责任,而而仅仅负责责 消费费 产品品(正如暴暴发户所为为)。下面面我们从开开闭原则上上来分析下下简单工厂厂模式。当当暴发户增增加了一辆辆车的时候候,只要符符合抽象产产品制定的的合同,那那么只要
9、通通知工厂类类知道就可可以被客户户使用了。那那么对于产产品部分来来说,它是是符合开闭闭原则的- 对扩扩展开放、对对修改关闭闭;但是工工厂部分好好像不太理理想,因为为每增加一一辆车,都都要在工厂厂类中增加加相应的商商业逻辑和和判断逻辑辑,这显自自然是违背背开闭原则则的。对于于这样的工工厂类(在在我们的例例子中是为为司机师傅傅),我们们称它为全全能类或者者上帝类。我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了,进而累坏了我们可爱的程序员:( 正如我前面提到的简单工厂模式适用于业务将简单的情
10、况下。而对于复杂的业务环境可能不太适应阿。这就应该由工厂方法模式来出场了! 四、工厂方方法模式先先来看下它它的组成吧吧:1、抽抽象工厂角角色:这是是工厂方法法模式的核核心,它与与应用程序序无关。是是具体工厂厂角色必须须实现的接接口或者必必须继承的的父类。在在javaa 中它由由抽象类或或者接口来来实现。22、具体工工厂角色:它含有和和具体业务务逻辑有关关的代码。由由应用程序序调用以创创建对应的的具体产品品的对象。在在javaa 中它由由具体的类类来实现。3、抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java 中一般有抽象类或者接口来实现。4、具体产品角色:具体工厂角色所创建的对象
11、就是此角色的实例。在java 中由具体的类来实现。来用类图来清晰的表示下的它们之间的关系: 我们还是老老规矩使用用一个完整整的例子来来看看工厂厂模式各个个角色之间间是如何来来协调的。话话说暴发户户生意越做做越大,自自己的爱车车也越来越越多。这可可苦了那位位司机师傅傅了,什么么车它都要要记得,维维护,都要要经过他来来使用!于于是暴发户户同情他说说:看你跟跟我这么多多年的份上上,以后你你不用这么么辛苦了,我我给你分配配几个人手手,你只管管管好他们们就行了!于是,工工厂方法模模式的管理理出现了。代代码如下:1. /抽象象产品角色色,具体产产品角色与与简单工厂厂模式类似似,只是变变得复杂了了些,这里里
12、略。 2. /抽象象工厂角色色 3. publiicinteerfacceDrriverr 4. publiicCaardrriverrCar(); 5. 6. publiicclasssBeenzDrriverrimpplemeentsDrivver 7. publiicCaardrriverrCar() 8. returrnnewBBenz(); 9. 10. 11. publiicclasssBmmwDriiverimpllemenntsDDriveer 12. publiicCaardrriverrCar() 13. returrnnewBBmw(); 14. 15. 16. ./应该
13、和具具体产品形形成对应关关系,这里里略. 17. /有请请暴发户先先生 18. publiicclasssMaagnatte 19. 20. publiicstatticvoiddmaiin(Sttringgaargs) 21. 22. try 23. Driveerdrriverr=nnewBBenzDDriveer(); 24. 25. Carccar=driiver.drivverCaar(); 26. car.ddrivee(); 27. catcch(Exxcepttione) 28. 29. 30. 工厂方法使使用一个抽抽象工厂角角色作为核核心来代替替在简单工工厂模式中中使用具体体
14、类作为核核心。让我我们来看看看工厂方法法模式给我我们带来了了什么?使使用开闭原原则来分析析下工厂方方法模式。当当有新的产产品(即暴暴发户的汽汽车)产生生时,只要要按照抽象象产品角色色、抽象工工厂角色提提供的合同同来生成,那那么就可以以被客户使使用,而不不必去修改改任何已有有的代码。看看来,工厂厂方法模式式是完全符符合开闭原原则的!使使用工厂方方法模式足足以应付我我们可能遇遇到的大部部分业务需需求。但是是当产品种种类非常多多时,就会会出现大量量的与之对对应的工厂厂类,这不不应该是我我们所希望望的。所以以我建议在在这种情况况下使用简简单工厂模模式与工厂厂方法模式式相结合的的方式来减减少工厂类类:即
15、对于于产品树上上类似的种种类(一般般是树的叶叶子中互为为兄弟的)使使用简单工工厂模式来来实现。当当然特殊的的情况,就就要特殊对对待了:对对于系统中中存在不同同的产品树树,而且产产品树上存存在产品族族,那么这这种情况下下就可能可可以使用抽抽象工厂模模式了。 五、小结让让我们来看看看简单工工厂模式、工工厂方法模模式给我们们的启迪:如果不使使用工厂模模式来实现现我们的例例子,也许许代码会减减少很多- 只需需要实现已已有的车,不不使用多态态。但是在在可维护性性上,可扩扩展性上是是非常差的的(你可以以想象一下下,添加一一辆车后要要牵动的类类)。因此此为了提高高扩展性和和维护性,多多写些代码码是值得的的。
16、 六、抽象工工厂模式先先来认识下下什么是产产品族:位位于不同产产品等级结结构中,功功能相关联联的产品组组成的家族族。如果光光看这句话话就能清楚楚的理解这这个概念,我我不得不佩佩服你啊。还还是让我们们用一个例例子来形象象地说明一一下吧。 图中的BmmwCarr 和BeenzCaar 就是是两个产品品树(产品品层次结构构);而如如图所示的的BenzzSporrtsCaar 和BBmwSpportssCar 就是一个个产品族。他他们都可以以放到跑车车家族中,因因此功能有有所关联。同同理BmwwBusssinesssCarr 和BeenzSpportssCar 也是一个个产品族。回到抽象产品模式的话题
17、上,可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:1. 系统中有多个产品族,而系统一次只可能消费其中一族产品2. 同属于同一个产品族的产品以其使用。来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java 中它由抽象类或者接口来实现。具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应
18、的具体产品的对象。在java 中它由具体的类来实现。抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java 中一般有抽象类或者接口来实现。具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java 中由具体的类来实现。 看过了前两两个模式,对对这个模式式各个角色色之间的协协调情况应应该心里有有个数了,我我就不举具具体的例子子了。只是是一定要注注意满足使使用抽象工工厂模式的的条件哦,不不然即使存存在了多个个产品树,也也存在产品品族,但是是不能使用用的。 附带一个例例子:htttp:/wwww.bloogjavva.neet/fllustaar/arrchivve/20007/1
19、11/299/facctoryyMethhod.hhtml 1. FactooryMMethood模式 2. publiicabsttracttcllassBalll 3. pproteecteddabsttracttvoiddpllay(); 4. 5. 6. publiicclasssBBaskeetballleextenndsBalll 7. 8. pproteecteddvooidplayy() 9. SSysteem.ouut.prrintlln(pplaythebaskketbaall); 10. 11. 12. 13. publiicclasssFFootbballexttend
20、ssBaall 14. 15. pproteecteddvooidplayy() 16. SSysteem.ouut.prrintlln(pplaythefoottballl); 17. 18. 19. 20. publiicabsttracttcllassBalllFacctoryy 21. pproteecteddabsttracttBaallmmakeBBall(); 22. 23. 24. publiicclasssBBaskeetballlFaccteextenndsBalllFacttory 25. 26. pproteecteddBaallmmakeBBall() 27. rre
21、turrnnewBaskketbaall(); 28. 29. 30. 31. publiicclasssFFootbballFFactexttendssBaallFaactorry 32. 33. pproteecteddBaallmmakeBBall() 34. rreturrnnewFoottballl(); 35. 36. 37. 38. publiicclasssCCliennt 39. 40. ppubliicstatticvoiidmmain(Striingarggs) 41. 42. BBallFFactoorybballFFactoory=newwBaaskettballlFactt(); 43. BBallbaskketbaall=balllFacctoryy.makkeBalll(); 44. bbaskeetballl.pllay(); 45. 46. bballFFactoory=newwFoootbaallFaact(); 47. BBallfoottballl=bballFFactoory.mmakeBBall(); 48. ffootbball.playy(); 49. 50.