




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1有关对象创建-new按照前面介绍的设计原则,我们应该面向接口编程而不是面向实现编程,因为面向实现编程会使得我们的设计更脆弱,缺乏灵活性。但是我们每次使用new时,是不是正在违背这一原则呢?我们想用接口但却必须建立一个具体类的实例Duckduck=newMallardDuck()PizzaFactory2问题…当你拥有一组相关的具体类时,你常常被迫写出类似下面的代码:Duckduck;If(picnic){duck=newMallardDuck();}elseif(hunting){duck=newDecoyDuck();}elseif(inBathTub){duck=newRubberDuck();}这样做的原因是直到运行时我们才知道需要实例化那个类。这样做的后果是如果应用要做变化或扩展,往往要修改这段代码。这使得维护困难并容易引入错误。PizzaFactory3问题在哪里?是new的问题吗?从技术上来说,new并没有任何问题。new是java最基本的部分。那么问题在哪里?真正的问题在于“变化”如果对接口编程,我们可实现与许多“变化”的隔离,因为通过多态机制,你的代码对于实现接口的新类依然适用。但是使用具体类麻烦就来了,因为增加新的具体类时相应代码可能就必须修改。PizzaFactory4PizzaPizzaFactory5Pizza的生产过程Pizzastore的主要步骤客户点pizza准备pizza原料,制作一个生的pizza烘烤切割成块Pizza装盒为客户呈上pizza成品PizzaFactory6Pizzastore-orderPizza方法PublicClassPizzaStore{
//…othercode
PizzaorderPizza(){Pizzapizza=newPizza();pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}//…othercode}为了让系统有弹性,希望这是一个抽象类或者接口,可惜抽象类或接口都不能被实例化而且,我们有许多种pizza,所以我们增加一些代码,来确定合适的pizza种类,然后进行制作。PizzaFactory7pizza种类扩展后的类图CheesePizzapepperoniGreekPizzapizzaPizzaFactory8修改后的代码PizzaorderPizza(Stringtype){Pizzapizza;if(type.equals(“cheese”)){pizza=newCheesePizza();}elseif(type.equals(“greek”)){pizza=newGreekPizza();}elseif(type.equals(“pepperoni”)){pizza=newPepperoniPizza();}pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}根据接受的类型,创建相应的pizza实例,并赋值给实例变量。(注意:各种pizza实现接口Pizza)传递pizza的类型给方法orderPizza每一种pizza子类型都知道其制作方法PizzaFactory9适应市场,改变pizza种类其他pizza店推出了新产品,我们也得增加!例如VeggiePizza。GreekPizza最近不受欢迎,把它从菜单中取消。于是…PizzaFactory10修改代码PizzaorderPizza(Stringtype){Pizzapizzaif(type.equals(“cheese”)){
pizza=newCheesePizza();}elseif(type.equals(“greek”)){pizza=newGreekPizza();}elseif(type.equals(“pepperoni”)){pizza=newPepperoniPizza();}elseif(type.equals(“veggie”)){pizza=newVeggiePizza();}pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}这是变化的部分。随着Pizza菜单的变化,这部分要跟着不断地变。这部分是不变的部分。PizzaFactory11分离变化点PizzaorderPizza(Stringtype){Pizzapizzaif(type.equals(“cheese”)){
pizza=newCheesePizza();}elseif(type.equals(“greek”)){pizza=newGreekPizza();}elseif(type.equals(“pepperoni”)){pizza=newPepperoniPizza();}elseif(type.equals(“veggie”)){pizza=newVeggiePizza();}pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}把这部分封装在一个只管如何创建pizza的对象中if(type.equals(“cheese”)){
pizza=newCheesePizza();}elseif(type.equals(“greek”)){pizza=newGreekPizza();}elseif(type.equals(“pepperoni”)){pizza=newPepperoniPizza();}elseif(type.equals(“veggie”)){pizza=newVeggiePizza();}将创建pizza对象的代码从orderPizza方法中分离出去专门负责制作pizza的对象PizzaFactory12Pizza工厂PizzaorderPizza(Stringtype){Pizzapizza
pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}PizzaFactory要求制作pizzapizza这样,orderPizza方法就成为PizaFactory的客户。PizzaFactory13Pizza工厂代码publicclassSimplePizzaFactory{publicpizzacreatePizza(Stringtype){Pizzapizza=null;if(type.equals(“cheese”)){
pizza=newCheesePizza();}elseif(type.equals(“pepperoni”)){pizza=newPepperoniPizza();}elseif(type.equals(“veggie”)){pizza=newVeggiePizza();}returnpizza;}}Pizza工厂中定义的“生产”pizza的方法。所有客户都可以用它来实例化新的pizza对象这部分代码就是从orderPizza()方法中抽出来的。和原来的方法一样,也是通过参数确定pizza的种类。PizzaFactory14设计类图PizzaStoreorderPizza()SimplePizzaFactorycreatePizza()PizzaPrepare()Bark()Cut()Box()CheesePizzaVeggiePizzaClamPizzaPepperoniPizzaPizzaFactory15讨论这看来好像我们只是把问题从一个对象推给了另一个对象!这样做有什么好处?SimplePizzaFactory可以有许多个客户,这样,当实现改变时我们只需要修改SimplePizzaFactory,而不需修改众多的客户目前虽然只有orderPizza()方法是它的客户,可能还有PizzaShopMenu类利用这个工厂取得比萨的价格和描述,可能还有一个HomeDelivery类,会以PizzaShop类不同的方式来处理pizza。PizzaFactory16设计类图-SimplePizzaFactory可以有许多个客户PizzaStoreorderPizza()SimplePizzaFactorycreatePizza()PizzaPrepare()Bark()Cut()Box()CheesePizzaVeggiePizzaClamPizzaPepperoniPizzaPizzaShopMenuHomeDeliveryOtherClassPizzaFactory17重写PizzaStore类-工厂产生Pizza对象publicclassPizzaStore{
SimplePizzaFactoryfactory;
publicPizzaStore(SimplePizzaFactoryfactory){this.factory=factory;}publicPizzaorderPizza(Stringtype){Pizzapizza;
pizza=factory.createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}//othermethodshere}PizzaFactory18新变化-授权pizza店我们的pizza店非常成功,许多人都想开设我们的授权加盟店。为保证质量,我们希望他们使用我们经过时间考验的代码。但是,不同地区的加盟pizza店可能希望供应不同口味的pizza。怎么解决这个问题呢?PizzaFactory19拟解决方案希望加盟点能利用原有的代码,好让pizza的加工流程不变纽约风味芝加哥风味PizzaFactory20拟解决方案代码/************************************该pizza店提供纽约风味的pizza,代码如下************************************///Step1:建立一个生产纽约风味pizza的工厂NYPizzaFactorynyFactory=newNYPizzaFactory();//Step2:建立一个pizza店,引用纽约风味pizza的工厂PizzaStorenyStore=newPizzaStore(nyFactory);//Step3:生产的是纽约风味的pizzanyStore.orderPizza(“Veggie”);//其他风味的Pizza工厂类似以上代码PizzaFactory21质量控制问题推广SimpleFactory方式时,发现加盟店虽然使用工厂生产pizza,但是其他部分采用了自创的流程。如烘烤,是否要切片。甚至有部分加盟店用别人的盒子。希望建立一个框架,把加盟店和创建pizza捆绑在一起的同时又保持一定的弹性。PizzaFactory22质量控制问题-流程控制推广SimpleFactory方式时,发现加盟店虽然使用工厂生产pizza,但是其他部分采用了自创的流程。如烘烤,是否要切片。甚至有部分加盟店用别人的盒子publicclassPizzaStore{
SimplePizzaFactoryfactory;
publicPizzaStore(SimplePizzaFactoryfactory){this.factory=factory;}publicPizzaorderPizza(Stringtype){Pizzapizza;
pizza=factory.createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}//othermethodshere}PizzaFactory23质量控制问题-捆绑与弹性限制希望建立一个框架,把加盟店和创建pizza捆绑在一起的同时又保持一定的弹性。如何捆绑在一起?如何又有弹性?PizzaFactory24新的设计思路step1-实现流程统一NYPizzaStoreNYPizzaFactoryChicagoPizzaStoreChicagoPizzaFactoryPizzaStorePizzaFactoryorderPizza()createPizza()orderPizza()createPizza()createPizza()orderPizza()PizzaFactory25新的设计思路step1-实现流程统一PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactoryChicagoPizzaFactoryNYPizzaStoreChicagoPizzaStore实现了pizza制作流程的严格控制,但是PizzaFactory没有实现创新PizzaFactory26新的设计思路step2-实现制作独立PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactorycreatePizza()ChicagoPizzaFactorycreatePizza()NYPizzaStoreChicagoPizzaStore抽象类PizzaFactory27新的设计思路step3-全局PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactorycreatePizza()ChicagoPizzaFactorycreatePizza()NYPizzaStoreChicagoPizzaStorePizzaPrepare()Bark()Cut()Box()NYVeggiePizzaNYClamPizzaNYCheesePizzaNYVeggiePizzaNYClamPizzaNYCheesePizzaPizzaFactory28新的设计思路step4-实现绑定PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaStoreChicagoPizzaStorePizzaPrepare()Bark()Cut()Box()NYVeggiePizzaNYClamPizzaNYCheesePizzaNYVeggiePizzaNYClamPizzaNYCheesePizzacreatePizza()createPizza()PizzaFactory29最终结构PizzaStoreorderPizza()NYPizzaStoreChicagoPizzaStorePizzaPrepare()Bark()Cut()Box()NYVeggiePizzaNYClamPizzaNYCheesePizzaNYVeggiePizzaNYClamPizzaNYCheesePizzacreatePizza()createPizza()createPizza()PizzaFactory30改造后的PizzaStore的代码publicabstractclassPizzaStore{
publicPizzaorderPizza(Stringtype){Pizzapizza=createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}
abstractPizzacreatePizza(Stringtype);}在PizzaStore内调用自身的一个方法来制造pizza,而不是使用一个factory对象factory对象成了这里的一个抽象方法下面我们需要PizzaStore的各种子类(对应不同的地区风味)PizzaFactory31讨论:为什么说是由子类做决定的?PizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()publicabstractclassPizzaStore{
publicPizzaorderPizza(Stringtype){Pizzapizza=createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}
abstractPizzacreatePizza(Stringtype);}PizzaFactory32让子类做决定PizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()PizzacreatePizza(Stringitem){if(item.equals(“奶酪")){ returnnewNYStyleCheesePizza();}elseif(item.equals(“蔬菜")){ returnnewNYStyleVeggiePizza();}elseif(item.equals(“卡姆")){ returnnewNYStyleClamPizza();}elseif(item.equals(“辣香肠")){ returnnewNYStylePepperoniPizza();}elsereturnnull;}PizzaFactory33现在让我们来编写子类NYPizzaStorePizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()publicclassNYPizzaStoreextendsPizzaStore{PizzacreatePizza(Stringitem){if(item.equals(“奶酪")){ returnnewNYStyleCheesePizza();}elseif(item.equals(“蔬菜")){ returnnewNYStyleVeggiePizza();}elseif(item.equals(“卡姆")){ returnnewNYStyleClamPizza();}elseif(item.equals(“辣香肠")){ returnnewNYStylePepperoniPizza();}elsereturnnull;}}PizzaFactory34怎么编写子类ChicagoPizzaStore?怎么编写子类ChicagoPizzaStore?publicclassChicagoPizzaStoreextendsPizzaStore{PizzacreatePizza(Stringitem){if(item.equals(“奶酪")){ returnnewChicagoStyleCheesePizza();}elseif(item.equals(“蔬菜")){ returnnewChicagoStyleVeggiePizza();}elseif(item.equals(“卡姆")){ returnnewChicagoStyleClamPizza();}elseif(item.equals(“辣香肠")){ returnnewChicagoStylePepperoniPizza();}elsereturnnull;}}PizzaFactory35声明工厂方法publicabstractclassPizzaStore{
publicPizzaorderPizza(Stringtype){
Pizzapizza=createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}
abstractPizzacreatePizza(Stringtype);}实例化pizza的责任现在由一个方法承担。该方法相当于一个工厂。我们称之为工厂方法。PizzaStore的子类用createPizza()方法处理对象的实例化。PizzaFactory36声明工厂方法abstractPizzacreatePizza(Stringtype);abstractProductfactoryMethod(Stringtype);工厂方法是抽象的,在一个超类中定义。必须由子类来实现。工厂方法返回一个产品,该产品通常在其所在类的方法中定义。(如orderPizza())工厂方法通常提供参数,用以选择一个产品的不同品种。工厂方法将客户(超类中的方法,如PizzaStore中的orderPizza())与具体的产品相隔离。PizzaFactory37声明工厂方法abstractPizzacreatePizza(Stringtype);abstractProductfactoryMethod(Stringtype);工厂方法是抽象的,在一个超类中定义。必须由子类来实现。工厂方法返回一个产品,该产品通常在其所在类的方法中定义。(如orderPizza())工厂方法通常提供参数,用以选择一个产品的不同品种。工厂方法将客户(超类中的方法,如PizzaStore中的orderPizza())与具体的产品相隔离。PizzaFactory38工厂方法怎么工作?假定张三喜欢纽约风味的pizza,李四喜欢芝加哥风味的pizza。需要相应Pizza店的实例调用orderPizza()订购想要的pizza品种CreatePizza()被调用,并返回pizza到orderPizza()方法。尽管不知道是什么pizza,但orderPizza()仍知道对它进行后续处理。PizzaFactory39以张三订购pizza为例//首先需要一个pizza店PizzaStorenyPizzaStore=newNYPizzaStore();//对pizza店下订单nyPizzaStore.orderPizza(“cheese”)
;//在orderPizza()方法中调用Createpizza()Pizzapizza=createPizza(“cheese”)
;//对pizza进行其他的工作pizza.prepare();pizza.bake();pizza.cut();pizza.box();PizzaFactory40Pizza类源代码importjava.util.ArrayList;public
abstractclassPizza{ Stringname; Stringdough;//生面团
Stringsauce; ArrayListtoppings=newArrayList(); voidprepare(){ System.out.println("Preparing"+name); System.out.println("Tossingdough..."); System.out.println("Addingsauce..."); System.out.println("Addingtoppings:"); for(inti=0;i<toppings.size();i++){ System.out.println(""+toppings.get(i)); } }voidbake(){System.out.println("Bakefor25minutesat350");} voidcut(){System.out.println("Cuttingthepizzaintodiagonalslices");} voidbox(){System.out.println("PlacepizzainofficialPizzaStorebox");} publicStringgetName(){returnname;}}PizzaFactory41NYStyleCheesePizzapublicclassNYStyleCheesePizzaextendsPizza{ publicNYStyleCheesePizza(){ name="NYStyleSauceandCheesePizza"; dough="ThinCrustDough"; sauce="MarinaraSauce"; toppings.add("GratedReggianoCheese"); }}PizzaFactory42ChicagoStyleCheesePizzapublicclassChicagoStyleCheesePizzaextendsPizza{ publicChicagoStyleCheesePizza(){ name="ChicagoStyleDeepDishCheesePizza"; dough="ExtraThickCrustDough"; sauce="PlumTomatoSauce"; toppings.add("ShreddedMozzarellaCheese"); }
voidcut(){ System.out.println("Cuttingthepizzaintosquareslices"); }}PizzaFactory43测试类publicclassPizzaTestDrive{ publicstaticvoidmain(String[]args){ PizzaStorenyStore=newNYPizzaStore(); PizzaStorechicagoStore=newChicagoPizzaStore(); Pizzapizza=nyStore.orderPizza("cheese"); System.out.println(“张三ordereda"+pizza.getName()+"\n"); pizza=chicagoStore.orderPizza("cheese"); System.out.println(“李四ordereda"+pizza.getName()+"\n"); }}PizzaFactory44工厂方法模式中的类
—创建者类TheCreatorclassesPizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()AbstractcreatorConcretecreatorsPizzaFactory45工厂方法模式中的类
—产品类TheProductclassesPizzaNYStyleCheesePizzaChicagoStyleCheesePizzacreatePizza()NYStylePepperoniPizzaNYStyleCalmPizzaNYStyleVeggiePizzaChicagoStylePepperoniPizzacreatePizza()ChicagoStyleCalmPizzacreatePizza()ChicagoStyleVeggiePizzacreatePizza()AbstractproductConcreteproductsPizzaFactory46平行的类层次PizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()NYStyleCheesePizzaChicagoStyleCheesePizzacreatePizza()NYStylePepperoniPizzaNYStyleCalmPizzaNYStyleVeggiePizzaChicagoStylePepperoniPizzacreatePizza()ChicagoStyleCalmPizzacreatePizza()ChicagoStyleVeggiePizzacreatePizza()publicclassNYPizzaStoreextendsPizzaStore{PizzacreatePizza(Stringitem){if(item.equals(“奶酪")){ returnnewNYStyleCheesePizza();}elseif(item.equals(“蔬菜")){ returnnewNYStyleVeggiePizza();}elseif(item.equals(“卡姆")){ returnnewNYStyleClamPizza();}elseif(item.equals(“辣香肠")){ returnnewNYStylePepperoniPizza();}elsereturnnull;}}PizzaFactory47工厂方法模式的正式定义定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式让一个类的实例化延迟到其子类。PizzaFactory48工厂方法模式的结构ProductConcreteCreatorfactoryMethod()ConcreteProductCreatorfactoryMethod()anOperationPizzaFactory49总结:FactoryMethod模式意图
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2030年不锈钢N型拉手项目投资价值分析报告
- 2024-2025学年高中数学课时分层作业17概率的加法公式含解析新人教B版必修3
- 《10的加、减法》(教学设计)-2024-2025学年一年级上册数学人教版
- 2024-2028年中国建筑信息化行业市场发展现状及投资方向研究报告
- 沪科版 信息技术 选修三 第二章 第二节 任务二 安装通信软件与设置参数理论 IP地址初探 教学设计
- 中国手摇灯项目投资可行性研究报告
- 2020-2025年中国玩偶行业市场调查研究及投资前景预测报告
- 2025年中国复合易撕膜市场调查研究及行业投资潜力预测报告
- “十三五”规划重点-酒石酸唑吡坦片项目建议书(立项报告)
- 融资佣金合同范本
- 人教版小学劳动教育三年级下册第二章劳动项目5《蒸蛋羹》优质课教学设计
- 概率论与数理统计智慧树知到课后章节答案2023年下四川师范大学
- DataOps实践指南(1.0)-中文版-2023.07
- 新生儿败血症护理查房查房
- 鞋业-品质培训
- 中级会计实务所得税课件
- 起重指挥人员安全操作规程
- 精神分裂症的护理PPT
- JJG875-2005数字压力计检定规程
- 中小学生安全教育手册全面版
- 09《马克思主义政治经济学概论(第二版)》第九章
评论
0/150
提交评论