JAVA 面向?qū)ο蠼?jīng)典HeadFirst-Factory_第1頁
JAVA 面向?qū)ο蠼?jīng)典HeadFirst-Factory_第2頁
JAVA 面向?qū)ο蠼?jīng)典HeadFirst-Factory_第3頁
JAVA 面向?qū)ο蠼?jīng)典HeadFirst-Factory_第4頁
JAVA 面向?qū)ο蠼?jīng)典HeadFirst-Factory_第5頁
已閱讀5頁,還剩50頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1有關(guān)對象創(chuàng)建-new按照前面介紹的設(shè)計原則,我們應該面向接口編程而不是面向?qū)崿F(xiàn)編程,因為面向?qū)崿F(xiàn)編程會使得我們的設(shè)計更脆弱,缺乏靈活性。但是我們每次使用new時,是不是正在違背這一原則呢?我們想用接口但卻必須建立一個具體類的實例Duckduck=newMallardDuck()PizzaFactory2問題…當你擁有一組相關(guān)的具體類時,你常常被迫寫出類似下面的代碼:Duckduck;If(picnic){duck=newMallardDuck();}elseif(hunting){duck=newDecoyDuck();}elseif(inBathTub){duck=newRubberDuck();}這樣做的原因是直到運行時我們才知道需要實例化那個類。這樣做的后果是如果應用要做變化或擴展,往往要修改這段代碼。這使得維護困難并容易引入錯誤。PizzaFactory3問題在哪里?是new的問題嗎?從技術(shù)上來說,new并沒有任何問題。new是java最基本的部分。那么問題在哪里?真正的問題在于“變化”如果對接口編程,我們可實現(xiàn)與許多“變化”的隔離,因為通過多態(tài)機制,你的代碼對于實現(xiàn)接口的新類依然適用。但是使用具體類麻煩就來了,因為增加新的具體類時相應代碼可能就必須修改。PizzaFactory4PizzaPizzaFactory5Pizza的生產(chǎn)過程Pizzastore的主要步驟客戶點pizza準備pizza原料,制作一個生的pizza烘烤切割成塊Pizza裝盒為客戶呈上pizza成品PizzaFactory6Pizzastore-orderPizza方法PublicClassPizzaStore{

//…othercode

PizzaorderPizza(){Pizzapizza=newPizza();pizza.prepare();pizza.bake();pizza.cut();pizza.box();returnpizza;}//…othercode}為了讓系統(tǒng)有彈性,希望這是一個抽象類或者接口,可惜抽象類或接口都不能被實例化而且,我們有許多種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;}根據(jù)接受的類型,創(chuàng)建相應的pizza實例,并賦值給實例變量。(注意:各種pizza實現(xiàn)接口Pizza)傳遞pizza的類型給方法orderPizza每一種pizza子類型都知道其制作方法PizzaFactory9適應市場,改變pizza種類其他pizza店推出了新產(chǎn)品,我們也得增加!例如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;}把這部分封裝在一個只管如何創(chuàng)建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();}將創(chuàng)建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工廠中定義的“生產(chǎn)”pizza的方法。所有客戶都可以用它來實例化新的pizza對象這部分代碼就是從orderPizza()方法中抽出來的。和原來的方法一樣,也是通過參數(shù)確定pizza的種類。PizzaFactory14設(shè)計類圖PizzaStoreorderPizza()SimplePizzaFactorycreatePizza()PizzaPrepare()Bark()Cut()Box()CheesePizzaVeggiePizzaClamPizzaPepperoniPizzaPizzaFactory15討論這看來好像我們只是把問題從一個對象推給了另一個對象!這樣做有什么好處?SimplePizzaFactory可以有許多個客戶,這樣,當實現(xiàn)改變時我們只需要修改SimplePizzaFactory,而不需修改眾多的客戶目前雖然只有orderPizza()方法是它的客戶,可能還有PizzaShopMenu類利用這個工廠取得比薩的價格和描述,可能還有一個HomeDelivery類,會以PizzaShop類不同的方式來處理pizza。PizzaFactory16設(shè)計類圖-SimplePizzaFactory可以有許多個客戶PizzaStoreorderPizza()SimplePizzaFactorycreatePizza()PizzaPrepare()Bark()Cut()Box()CheesePizzaVeggiePizzaClamPizzaPepperoniPizzaPizzaShopMenuHomeDeliveryOtherClassPizzaFactory17重寫PizzaStore類-工廠產(chǎn)生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新變化-授權(quán)pizza店我們的pizza店非常成功,許多人都想開設(shè)我們的授權(quán)加盟店。為保證質(zhì)量,我們希望他們使用我們經(jīng)過時間考驗的代碼。但是,不同地區(qū)的加盟pizza店可能希望供應不同口味的pizza。怎么解決這個問題呢?PizzaFactory19擬解決方案希望加盟點能利用原有的代碼,好讓pizza的加工流程不變紐約風味芝加哥風味PizzaFactory20擬解決方案代碼/************************************該pizza店提供紐約風味的pizza,代碼如下************************************///Step1:建立一個生產(chǎn)紐約風味pizza的工廠NYPizzaFactorynyFactory=newNYPizzaFactory();//Step2:建立一個pizza店,引用紐約風味pizza的工廠PizzaStorenyStore=newPizzaStore(nyFactory);//Step3:生產(chǎn)的是紐約風味的pizzanyStore.orderPizza(“Veggie”);//其他風味的Pizza工廠類似以上代碼PizzaFactory21質(zhì)量控制問題推廣SimpleFactory方式時,發(fā)現(xiàn)加盟店雖然使用工廠生產(chǎn)pizza,但是其他部分采用了自創(chuàng)的流程。如烘烤,是否要切片。甚至有部分加盟店用別人的盒子。希望建立一個框架,把加盟店和創(chuàng)建pizza捆綁在一起的同時又保持一定的彈性。PizzaFactory22質(zhì)量控制問題-流程控制推廣SimpleFactory方式時,發(fā)現(xiàn)加盟店雖然使用工廠生產(chǎn)pizza,但是其他部分采用了自創(chuàng)的流程。如烘烤,是否要切片。甚至有部分加盟店用別人的盒子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質(zhì)量控制問題-捆綁與彈性限制希望建立一個框架,把加盟店和創(chuàng)建pizza捆綁在一起的同時又保持一定的彈性。如何捆綁在一起?如何又有彈性?PizzaFactory24新的設(shè)計思路step1-實現(xiàn)流程統(tǒng)一NYPizzaStoreNYPizzaFactoryChicagoPizzaStoreChicagoPizzaFactoryPizzaStorePizzaFactoryorderPizza()createPizza()orderPizza()createPizza()createPizza()orderPizza()PizzaFactory25新的設(shè)計思路step1-實現(xiàn)流程統(tǒng)一PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactoryChicagoPizzaFactoryNYPizzaStoreChicagoPizzaStore實現(xiàn)了pizza制作流程的嚴格控制,但是PizzaFactory沒有實現(xiàn)創(chuàng)新PizzaFactory26新的設(shè)計思路step2-實現(xiàn)制作獨立PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactorycreatePizza()ChicagoPizzaFactorycreatePizza()NYPizzaStoreChicagoPizzaStore抽象類PizzaFactory27新的設(shè)計思路step3-全局PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaFactorycreatePizza()ChicagoPizzaFactorycreatePizza()NYPizzaStoreChicagoPizzaStorePizzaPrepare()Bark()Cut()Box()NYVeggiePizzaNYClamPizzaNYCheesePizzaNYVeggiePizzaNYClamPizzaNYCheesePizzaPizzaFactory28新的設(shè)計思路step4-實現(xiàn)綁定PizzaFactoryPizzaStoreorderPizza()createPizza()NYPizzaStoreChicagoPizzaStorePizzaPrepare()Bark()Cut()Box()NYVeggiePizzaNYClamPizzaNYCheesePizzaNYVeggiePizzaNYClamPizzaNYCheesePizzacreatePizza()createPizza()PizzaFactory29最終結(jié)構(gòu)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內(nèi)調(diào)用自身的一個方法來制造pizza,而不是使用一個factory對象factory對象成了這里的一個抽象方法下面我們需要PizzaStore的各種子類(對應不同的地區(qū)風味)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現(xiàn)在讓我們來編寫子類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的責任現(xiàn)在由一個方法承擔。該方法相當于一個工廠。我們稱之為工廠方法。PizzaStore的子類用createPizza()方法處理對象的實例化。PizzaFactory36聲明工廠方法abstractPizzacreatePizza(Stringtype);abstractProductfactoryMethod(Stringtype);工廠方法是抽象的,在一個超類中定義。必須由子類來實現(xiàn)。工廠方法返回一個產(chǎn)品,該產(chǎn)品通常在其所在類的方法中定義。(如orderPizza())工廠方法通常提供參數(shù),用以選擇一個產(chǎn)品的不同品種。工廠方法將客戶(超類中的方法,如PizzaStore中的orderPizza())與具體的產(chǎn)品相隔離。PizzaFactory37聲明工廠方法abstractPizzacreatePizza(Stringtype);abstractProductfactoryMethod(Stringtype);工廠方法是抽象的,在一個超類中定義。必須由子類來實現(xiàn)。工廠方法返回一個產(chǎn)品,該產(chǎn)品通常在其所在類的方法中定義。(如orderPizza())工廠方法通常提供參數(shù),用以選擇一個產(chǎn)品的不同品種。工廠方法將客戶(超類中的方法,如PizzaStore中的orderPizza())與具體的產(chǎn)品相隔離。PizzaFactory38工廠方法怎么工作?假定張三喜歡紐約風味的pizza,李四喜歡芝加哥風味的pizza。需要相應Pizza店的實例調(diào)用orderPizza()訂購想要的pizza品種CreatePizza()被調(diào)用,并返回pizza到orderPizza()方法。盡管不知道是什么pizza,但orderPizza()仍知道對它進行后續(xù)處理。PizzaFactory39以張三訂購pizza為例//首先需要一個pizza店P(guān)izzaStorenyPizzaStore=newNYPizzaStore();//對pizza店下訂單nyPizzaStore.orderPizza(“cheese”)

;//在orderPizza()方法中調(diào)用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工廠方法模式中的類

—創(chuàng)建者類TheCreatorclassesPizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()AbstractcreatorConcretecreatorsPizzaFactory45工廠方法模式中的類

—產(chǎn)品類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工廠方法模式的正式定義定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法模式讓一個類的實例化延遲到其子類。PizzaFactory48工廠方法模式的結(jié)構(gòu)ProductConcreteCreatorfactoryMethod()ConcreteProductCreatorfactoryMethod()anOperationPizzaFactory49總結(jié):FactoryMethod模式意圖

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論