下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、The Factory Pattern(工廠模式),學(xué)習(xí)問題,隨著經(jīng)濟的全球化,一個軟件可能要在全球銷售。因此,我們設(shè)計的軟件應(yīng)該能夠通過簡單的配置就可以適應(yīng)不同的國家。 本講所學(xué)的知識將能提供一種有助于解決此問題的方法。,對象創(chuàng)建問題,關(guān)于new: 按照面向抽象的設(shè)計原則,我們應(yīng)該面向接口編程而不是面向?qū)崿F(xiàn)編程。但是我們每次使用new時,是不是正在違背這一原則呢?,我們想用接口,但卻必須建立一個具體類的實例,Duck duck = new MallardDuck(),問題,當(dāng)你擁有一組相關(guān)的具體類時,你常常被迫寫出類似下面的代碼: Duck duck; If (picnic) duck=ne
2、w MallardDuck(); else if (hunting) duck=new DecoyDuck(); else if (inBathTub) duck=new RubberDuck(); ,這樣做的原因是直到運行時我們才知道需要實例化那個類。,這樣做的后果是如果應(yīng)用要做變化或擴展,往往要修改這段代碼。這使得維護困難并容易引入錯誤。,問題在哪里?是new的問題嗎?,從技術(shù)上來說,new并沒有任何問題。new是java最基本的部分。真正的問題在于“變化” 如果對接口編程,我們可實現(xiàn)與許多“變化”的隔離,因為通過多態(tài)機制,你的代碼對于實現(xiàn)接口的新類依然適用。但是使用具體類麻煩就來了,因為
3、增加新的具體類時相應(yīng)代碼可能就必須修改。,怎么辦呢?,Duck duck = new MallardDuck() 上面這段代碼所在的模塊與MallardDuck模塊形成了耦合。,再回憶我們前面提出的面向?qū)ο笤O(shè)計的原則,識別應(yīng)用的變化部分,并將之與固定的部分相分離。,區(qū)分變化的部分,下面我們來看一個例子 Pizza店,披薩,PizzaStore類中的一段代碼-訂做pizza,Public Class PizzaStore / Pizza orderPizza() Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut
4、(); pizza.box(); return pizza; / ,真希望這是一個抽象類或者接口,可惜抽象類或接口都不能被實例化,而且,我們有許多種pizza,所以我們增加一些代碼,來確定合適的pizza種類,然后進(jìn)行制作。,修改后的代碼,Pizza orderPizza(String type) Pizza pizza; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“greek”) pizza = new GreekPizza(); else if (type.equals(“pepper
5、oni”) pizza = new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,根據(jù)接受的類型,創(chuàng)建相應(yīng)的pizza實例,并賦值給實例變量。(注意:各種pizza實現(xiàn)接口Pizza),傳遞pizza的類型給方法orderPizza,每一種pizza子類型都知道其制作方法,由于市場競爭。,其他pizza店推出了新產(chǎn)品,我們也得增加!例如VeggiePizza。 GreekPizza最近不受歡迎,把它從菜單中取消。 于是。,改!改!改!,Pizza orderPi
6、zza(String type) Pizza pizza; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“greek”) pizza = new GreekPizza(); else if (type.equals(“pepperoni”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cu
7、t(); pizza.box(); return pizza; ,變與不變,變與不變,Pizza orderPizza(String type) Pizza pizza; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“greek”) pizza = new GreekPizza(); else if (type.equals(“pepperoni”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = ne
8、w VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,這是變化的部分。隨著Pizza菜單的變化,這部分要跟著不斷地變。,這部分是不變的部分。,分離,Pizza orderPizza(String type) Pizza pizza; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“greek”) pizza = new GreekPizza(); else if (typ
9、e.equals(“pepperoni”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,把這部分封裝在一個只管如何創(chuàng)建pizza的對象中,if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“greek”) pizza = ne
10、w GreekPizza(); else if (type.equals(“pepperoni”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); ,將創(chuàng)建pizza對象的 代碼從orderPizza方法 中分離出去,專管制作 pizza的對象,我們將專管制作pizza的對象叫做Pizza工廠,Pizza orderPizza(String type) Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); p
11、izza.box(); return pizza; ,PizzaFactory,要求制作pizza,pizza,這樣,orderPizza方法就成為PizaFactory的客戶。,Pizza工廠-SimplePizzaFactory,public class SimplePizzaFactory public Pizza createPizza(String type) Pizza pizza=null; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“pepperoni”) pizza =
12、new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); return pizza; ,Pizza工廠中定義了 “生產(chǎn)”pizza的方法。所有客戶都可以用它來實例化新的pizza對象,這部分代碼就是從orderPizza()方法中抽出來的。和原來的方法一樣,也是通過參數(shù)確定pizza的種類。,思考一下!,這看來好像我們只是把問題從一個對象推給了另一個對象!這樣做有什么好處呢? 可以解除客戶代碼(PizzaStore)與具體Pizza的耦合。 SimplePizzaFactory可以有許多個客戶
13、,這樣,當(dāng)實現(xiàn)改變時我們只需要修改SimplePizzaFactory,而不需修改眾多的客戶。 提高了聚合度,PizzaStore的職責(zé)是使用pizza對象, SimplePizzaFactory的職責(zé)是決定創(chuàng)建什么樣的pizza對象。,重寫PizzaStore類,public class PizzaStore SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) this.factory = factory; public Pizza orderPizza(String type) Pizza pi
14、zza; pizza=factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; /other methods here ,簡單工廠模式,Pizza可以是一個抽象類,也可以是一個接口。,框架,框架的 對外接口,簡單工廠模式,有人認(rèn)為這還不是一個真正的模式,只是一種程序設(shè)計的習(xí)慣。,授權(quán)pizza店,我們的pizza店非常成功,許多人都想開設(shè)我們的授權(quán)加盟店。 但是,不同地區(qū)的加盟pizza店可能希望供應(yīng)不同口味的pizza。怎么解決這個問題呢?,解決方法之一:
15、建立不同的工廠,建立不同的工廠:如NYPizzaFactory、 ChicagoPizzaFactory、 CaliforniaPizzaFactory,在PizzaStore中包含相應(yīng)工廠的實例。其代碼類似于: /該pizza店提供紐約風(fēng)味的pizza NYPizzaFactory nyFactory=new NYPizzaFactory();/建立一個生產(chǎn)紐約風(fēng)味pizza的工廠 PizzaStore nyStore=new PizzaStore(nyFactory);/建立一個pizza店,引用紐約風(fēng)味pizza的工廠 nyStore.orderPizza(“Veggie”);/生產(chǎn)的是
16、紐約風(fēng)味的pizza /該pizza店提供芝加哥風(fēng)味的pizza ChicagoPizzaFactory chicagoFactory=new ChicagoPizzaFactory(); PizzaStore chicagoStore=new PizzaStore(chicagoFactory); chicagoStore.orderPizza(“Veggie”);,抽象工廠模式,這么多工廠,可以再增加抽象層 讓我們一起來設(shè)計,另一種解決方法-工廠方法模式,思路:改寫的PizzaStore,將createPizza()方法放回到PizzaStore,但是聲明為抽象方法,然后,為每一種地方風(fēng)味
17、創(chuàng)建一個PizzaStore的子類。,改造后的PizzaStore的代碼,public abstract class PizzaStore public Pizza orderPizza(String type) Pizza pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; abstract Pizza createPizza(String type); ,在PizzaStore內(nèi)調(diào)用自身的一個方法來制造pizza,而不是使用一個factory對象,
18、factory對象成了這里的一個抽象方法,下面我們需要PizzaStore的各種子類(對應(yīng)不同的地區(qū)風(fēng)味),讓子類做決定,ChicagoPizzaStore,createPizza(),Pizza createPizza(String item) if (item.equals(“奶酪) return new NYStyleCheesePizza(); else if (item.equals(“蔬菜) return new NYStyleVeggiePizza(); else if (item.equals(“卡姆) return new NYStyleClamPizza(); else i
19、f (item.equals(“辣香腸) return new NYStylePepperoniPizza(); else return null; ,討論:為什么說是由子類做決定的?,ChicagoPizzaStore,createPizza(),public abstract class PizzaStore public Pizza orderPizza(String type) Pizza pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; a
20、bstract Pizza createPizza(String type); ,現(xiàn)在讓我們來編寫子類NYPizzaStore,ChicagoPizzaStore,createPizza(),public class NYPizzaStore extends PizzaStore Pizza createPizza(String item) if (item.equals(“奶酪) return new NYStyleCheesePizza(); else if (item.equals(“蔬菜) return new NYStyleVeggiePizza(); else if (item.e
21、quals(“卡姆) return new NYStyleClamPizza(); else if (item.equals(“辣香腸) return new NYStylePepperoniPizza(); else return null; ,怎么編寫子類ChicagoPizzaStore?,試試看,聲明工廠方法,public abstract class PizzaStore public Pizza orderPizza(String type) Pizza pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.
22、cut(); pizza.box(); return pizza; abstract Pizza createPizza(String type); ,實例化pizza的責(zé)任現(xiàn)在由一個方法承擔(dān)。該方法相當(dāng)于一個工廠。我們稱之為工廠方法。,PizzaStore的子類用createPizza()方法處理對象的實例化。,聲明工廠方法,abstract Pizza createPizza(String type); abstract Product factoryMethod(String type); 工廠方法是抽象的,在一個超類中定義。必須由子類來實現(xiàn)。 工廠方法返回一個產(chǎn)品,該產(chǎn)品通常在其所在類
23、的方法中定義。(如orderPizza()) 工廠方法通常提供參數(shù),用以選擇一個產(chǎn)品的不同品種。 工廠方法將客戶(超類中的方法,如PizzaStore中的orderPizza())與具體的產(chǎn)品相隔離。,工廠方法怎么工作?,假定張三喜歡紐約風(fēng)味的pizza,李四喜歡芝加哥風(fēng)味的pizza。 需要相應(yīng)Pizza店的實例 調(diào)用orderPizza()訂購想要的pizza品種 createPizza()被調(diào)用,并返回pizza到orderPizza()方法。 盡管不知道是什么pizza,但orderPizza()仍知道對它進(jìn)行后續(xù)處理。,以張三訂購pizza為例,PizzaStore nyPizzaS
24、tore=new NYPizzaStore(); nyPizzaStore.orderPizza(“cheese”) 在orderPizza()方法中 Pizza pizza=createPizza (“cheese”) ; 在orderPizza()方法中 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box();,忘記了產(chǎn)品:pizza,先來個抽象的,import java.util.ArrayList; public abstract class Pizza String name; String dough; /生面團 String
25、 sauce; ArrayList toppings = new ArrayList(); void prepare() System.out.println(Preparing + name); System.out.println(Tossing dough.); System.out.println(Adding sauce.); System.out.println(Adding toppings: ); for (int i = 0; i toppings.size(); i+) System.out.println( + toppings.get(i); void bake() S
26、ystem.out.println(Bake for 25 minutes at 350); void cut() System.out.println(Cutting the pizza into diagonal slices); void box() System.out.println(Place pizza in official PizzaStore box); public String getName() return name; ,再來個具體的,public class NYStyleCheesePizza extends Pizza public NYStyleCheese
27、Pizza() name = NY Style Sauce and Cheese Pizza; dough = Thin Crust Dough; sauce = Marinara Sauce; toppings.add(Grated Reggiano Cheese); ,Marinara (mariners) sauce is an Italian red sauce usually made with tomatoes, garlic, herbs (such as basil), and onion,再來個另一風(fēng)味的,public class ChicagoStyleCheesePizz
28、a extends Pizza public ChicagoStyleCheesePizza() name = Chicago Style Deep Dish Cheese Pizza; dough = Extra Thick Crust Dough; sauce = Plum Tomato Sauce; toppings.add(Shredded Mozzarella Cheese); void cut() System.out.println(Cutting the pizza into square slices); ,測試主類,public class PizzaTestDrive p
29、ublic static void main(String args) PizzaStore nyStore = new NYPizzaStore(); PizzaStore chicagoStore = new ChicagoPizzaStore(); Pizza pizza = nyStore.orderPizza(cheese); System.out.println(“張三 ordered a + pizza.getName() + n); pizza = chicagoStore.orderPizza(cheese); System.out.println(“李四 ordered a
30、 + pizza.getName() + n); ,工廠方法模式中的類創(chuàng)建者類 The Creator classes,ChicagoPizzaStore,createPizza(),Abstract creator,Concrete creators,工廠方法模式中的類產(chǎn)品類 The Product classes,Abstract product,Concrete products,工廠方法模式的正式定義,在類中定義一個用于創(chuàng)建對象的接口方法,讓其子類決定實例化哪一個類。通過這種做法,使得工廠方法的客戶(工廠方法的使用者)不必了解具體應(yīng)該實例化哪一個類。 如: pizza = pizzaS
31、tore.orderPizza(cheese); 生產(chǎn)出來的匹薩是紐約風(fēng)味的還是芝加哥風(fēng)味的取決于pizzaStore引用的是哪個PizzaStore的子類,工廠方法模式的結(jié)構(gòu),總結(jié):Factory Method模式,意圖 定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法模式讓一個類的實例化延遲到其子類。使得對象的創(chuàng)建與對象的使用分離開來。 別名 虛擬構(gòu)造器,工廠方法模式的優(yōu)點與適用場景,優(yōu)點 讓用戶代碼與特定類Product的子類ConcretProduct的代碼解耦。 用戶不必知道它所使用的對象是怎么創(chuàng)建的,只需要知道這些對象的用法即可。 適用場景 希望讓用戶使用某些類,但不希望與這些類形成耦合(用new)。 用戶需要一個類的子類的實例,但不知道該類有哪些子類可用。,工廠方法模式的好處,用戶程序只需要和這些類打交道,總結(jié):Factory Method參與者,Produ
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 企業(yè)盤點制度
- 嚴(yán)格落實請休假制度
- 企業(yè)環(huán)保法規(guī)知識培訓(xùn)課件
- 2025-2030中國電警棍行業(yè)供給變化趨勢與發(fā)展現(xiàn)狀調(diào)研研究報告
- 2025-2030中國非那唑酮(安替比林)行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略研究報告
- 2025-2030中國腹膜透析(PD) 市場運營風(fēng)險與未來建設(shè)現(xiàn)狀研究研究報告
- 2025至2030中國工業(yè)型材市場需求變化與產(chǎn)能布局研究報告
- 2025-2030中國牛蛙飼料行業(yè)現(xiàn)狀調(diào)查與營銷策略分析研究報告
- 2025-2030中文教育機構(gòu)運營效率提升措施研究及海外招生渠道拓展計劃制定效果分析報告
- 2025至2030中國光伏發(fā)電行業(yè)政策支持力度與平價上網(wǎng)時代盈利模式研究報告
- 25年軍考數(shù)學(xué)試卷及答案
- 化工儲存設(shè)備知識培訓(xùn)課件
- 血透室水處理維護課件
- 服裝企業(yè)庫存優(yōu)化管理方案
- 低壓作業(yè)實操科目三安全隱患圖片題庫
- DB1331-T 114-2025 雄安新區(qū)近零碳變電站技術(shù)標(biāo)準(zhǔn)
- 面部血管解剖講解
- c1學(xué)法減分考試題庫及答案
- 恩施排污管理辦法
- 柔性引才協(xié)議書
- 廠區(qū)雜草施工方案(3篇)
評論
0/150
提交評論