您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > 设计模式培训-factorymethod
DesignPattern设计模式工厂方法模式张长春MSN:aphel_zhang@hotmail.com建立对象实例交给子类PDF文件使用pdfFactoryPro试用版本创建复习上一节课的内容•装饰模式:通过创建一个包装对象,也就是装饰来包裹真实的对象,在不修改被包装对象的基础之上实现新的功能。•设计原则–类的开-闭原则:类的设计应当支持扩展而拒绝修改!ComponentmethodA()methodB()//OthermethodsConcreteComponentmethodA()methodB()//OthermethodsDecoratormethodA()methodB()//OthermethodsConcreteDecoratorAComponentwrappedObjmethodA()methodB()newBehavior()//OthermethodsConcreteDecoratorBComponentwrappedObjObjectnewStatemethodA()methodB()//OthermethodscomponentPDF文件使用pdfFactoryPro试用版本创建复习上一节课的内容•到本节课程为止,我们学习了:•OO基础–抽象、封装、多态、继承•OO原则–封装变化–使用组合而不是继承–面向接口编程而不是实现–在相互影响的对象间努力做到松散耦合设计–类的开-闭原则•OO模式–策略模式Strategy–观查者模式Observer–装饰模式DecoratorPDF文件使用pdfFactoryPro试用版本创建写在课程之前……•接下来的课程我们来学习一些松耦合的OO设计。除了使用new操作以外,还有很多制造对象的方法。例如在本节课程中你将学习到实例化(instantiation),这是一种不总是被公开执行的行为,它经常导致耦合问题。当然,你不希望那样,不是吗?•OK,看工厂模式怎么把你从糟糕的依赖关系中拯救出来。PDF文件使用pdfFactoryPro试用版本创建仔细思考“new”带来的问题OK,现在我们已经学习了三个设计模式以及一些设计原则,可是仍然不能回答我的新的问题。我们不想面向实现编程,但是我随时都要使用新的东西,这就是我极力想解决的,你说对吗?当然,当你看到new的时候你马上就想实例化一个具体的类,这样就很明显是面向实现在编程而不是面向接口。不过这是一个好问题,你已经意识到了为一个具体的类编程将使得它比较脆弱并很少有弹性。Duckduck=newmallardDuck();我们本来是想通过接口来使得我们的代码更具备柔性但是在这里我们不得不为一个具体的类创建一个实例PDF文件使用pdfFactoryPro试用版本创建想想问题在哪里?当我们对一个相关的具体类有完整的设置时,通常我们不得不写这样的代码:Duckduck;if(picnic){duck=newMallardDuck();}elseif(hunting){duck=newDecoyDuck();}elseif(inBathTub){duck=newRubberDuck();}我们有很多不同的Duck类,并且除非在运行时被指定,否则我们不知道哪一种Duck类会被实例化运行时:例如野餐(picnic)时我们需要实例化野鸭(MallardDuck)当看到这样的代码,我们可以理解如果需求改变了或者功能扩展将花费我们大量时间,我们不得不重新打开代码来检查到底哪些地方需要增加(或者修改和删除)。通常这种类型的代码将使得应用程序的维护和更新变得更加困难,并且很容易出错。PDF文件使用pdfFactoryPro试用版本创建()方法有什么问题呢?但是你不得不在某些地方创建一个对象,并且Java中只提供了一种方法(new)来创建对象,不是吗?难道还有其他途径吗?从技术的角度来说,通过new来创建对象是没错的,毕竟,它是Java中提供的一项基本功能。其实错误的是我们前面曾经犯过的错,就是“变化”以及变化对我们使用new方法带来的影响。如果是面向接口的编程,我们可以隔离一些可能使得系统崩溃的变化。为什么呢?如果我们的代码是面向接口的,那么它可以为任何新的通过多态实现了这个接口的类工作。不过,当代码需要使用很多具体的类时,我们将发现一些麻烦,增加新的具体类的时候,我们不得不修改代码。所以,换句话说,我们的代码并不是“拒绝修改”的,如果要扩展新的具体类型时,我们不得不重新打开代码进行修改.那怎么办呢?让我们回想一下我们前面学习的第一个设计原则:识别在程序中的那些多变的特征,并且把它们和稳定的特征分离开来这里不符合我们前面讲的开-闭原则哈”!PDF文件使用pdfFactoryPro试用版本创建识别可变的特征……假定你拥有一家比萨店,作为一家切边比萨店的拥有者,你可能写这样的代码:PizzaorderPizza(){Pizzapizza=newPizza();pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}为了使得代码具备柔性和扩展能力,我们非常希望这是一个抽象类或者是个接口,但如果作为抽象类或者接口,我们将不能直接实例化它。比萨准备烘烤切边装盒比萨的制作过程PDF文件使用pdfFactoryPro试用版本创建但比萨有很多种类……PizzaorderPizza(Stringtype){Pizzapizza;if(type.equals(chesse)){pizza=newCheesePizza();}elseif(type.equals(greek)){pizza=newGreekPizza();}elseif(type.equals(pepperoni)){pizza=newPepperoniPizza();}pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}由于比萨的种类很多,所以你需要增加一些代码来定义你需要的比萨类型,并创建对应的实例:通过参数传递比萨的类型基于各种比萨的类型,我们实例化相应的类并且指派比萨实例变量。注意,在这里每一种比萨都已经不得不实现了Pizza这个接口类,即具体实现了prepare(),bake(),cut(),box()等方法。一旦我们获取了一种Pizza类(具体类),我们就调用该具体类的已经实现prepare(),bake(),cut(),box()的方法来制作,烘烤,切边以及装盒。每一个Pizza的子类型都均已实现了prepare(),bake(),cut(),box()的方法pepperoni意大利辣香肠PDF文件使用pdfFactoryPro试用版本创建真正有压力的是需要增加很多新的比萨种类你意识到你所有的竞争者在其菜单中已经增加了一组时尚的比萨种类:ClamPizza(蚧蛤比萨)和VeggiePizza(素食比萨)。很显然,你需要保持竞争力,因此你应当在你的菜单中也加入这两种比萨。并且你已经很久没有卖GreekPizza(希腊比萨)了,所以你决定从菜单中删除掉它。PizzaorderPizza(Stringtype){Pizzapizza;if(type.equals(chesse)){pizza=newCheesePizza();}elseif(type.equals(greek)){pizza=newGreekPizza();}elseif(type.equals(pepperoni)){pizza=newPepperoniPizza();}elseif(type.equals(clam)){pizza=newClamPizza();}elseif(type.equals(veggie)){pizza=newVeggiePizza();}pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}这就Pizza订单中常常变化的部分,每一次Pizza种类的不变化,你将不得不一次又一次的修改这些代码这些就是我们期望看到的不会变化的部分。对于大多数比萨种类来说,其制作,烹饪,和包装在多年都是不会产生变化的。所以我们不希望这部分代码产生变化,让具体的pizza自己操作自己的方法就可以了。这些代码并不是拒绝修改的。如果比萨店改变了比萨的供应菜单,我们将不得不进入这些代码来修改它。PDF文件使用pdfFactoryPro试用版本创建,我们现在意识到,我们最好是能够把对象的创建从oderPizza()中移出来。我们应该怎么做呢?我们可以把这部分代码转移到另外一个对象中,这个对象专门用来创建具体的比萨种类。PizzaorderPizza(Stringtype){Pizzapizza;pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}if(type.equals(chesse)){pizza=newCheesePizza();}elseif(type.equals(greek)){pizza=newGreekPizza();}elseif(type.equals(pepperoni)){pizza=newPepperoniPizza();}elseif(type.equals(clam)){pizza=newClamPizza();}elseif(type.equals(veggie)){pizza=newVeggiePizza();}首先我们把对象的创建部分的代码从orderPizza()方法中移出来。接下来我们把移出来的代码放在一个对象中,这个对象只需要关心怎么创建Pizza。如果其他对象需要某种pizza,则由这个对象来负责。现在我们知道有这么一个对象来专门负责生产或者创建pizza,我们可以把这个对象叫做Factory(工厂)。PDF文件使用pdfFactoryPro试用版本创建()和SimplePizzaFactory的关系orderPizza()Client负责具体Pizza的生产或创建在此处orderPizza()方法变成了对象SimplePizzaFactory的客户端了。当orderPizza()方法需要一份比萨时,它就要求SimplePizzaFactory生产一份给它。过去orderPizza()需要知道Greek与Clam比萨之间制作上的区别,但现在只需要关心它可以获得一个比萨对象就可以了,这个对象已经实现了Pizza接口,因此它可以调用prepare(),bake(),cut(),box()等方法。PDF文件使用pdfFactoryPro试用版本创建{publicPizzacreatePizza(Stringtype){Pizzapizza=null;if(type.equals(chesse)){pizza=newCheesePizza();}elseif(type.equals(pepperoni)){pizza=newPepperoniPizza();}elseif(type.equals(clam)){pizza=newClamPizza();}elseif(type.eq
本文标题:设计模式培训-factorymethod
链接地址:https://www.777doc.com/doc-987661 .html