java工廠設(shè)計(jì)模式.ppt
《java工廠設(shè)計(jì)模式.ppt》由會(huì)員分享,可在線閱讀,更多相關(guān)《java工廠設(shè)計(jì)模式.ppt(50頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
TheFactoryPattern 工廠模式 學(xué)習(xí)問題 隨著經(jīng)濟(jì)的全球化 一個(gè)軟件可能要在全球銷售 因此 我們設(shè)計(jì)的軟件應(yīng)該能夠通過簡單的配置就可以適應(yīng)不同的國家 本講所學(xué)的知識(shí)將能提供一種有助于解決此問題的方法 對象創(chuàng)建問題 關(guān)于new 按照面向抽象的設(shè)計(jì)原則 我們應(yīng)該面向接口編程而不是面向?qū)崿F(xiàn)編程 但是我們每次使用new時(shí) 是不是正在違背這一原則呢 我們想用接口 但卻必須建立一個(gè)具體類的實(shí)例 Duckduck newMallardDuck 問題 當(dāng)你擁有一組相關(guān)的具體類時(shí) 你常常被迫寫出類似下面的代碼 Duckduck If picnic duck newMallardDuck elseif hunting duck newDecoyDuck elseif inBathTub duck newRubberDuck 這樣做的原因是直到運(yùn)行時(shí)我們才知道需要實(shí)例化那個(gè)類 這樣做的后果是如果應(yīng)用要做變化或擴(kuò)展 往往要修改這段代碼 這使得維護(hù)困難并容易引入錯(cuò)誤 問題在哪里 是new的問題嗎 從技術(shù)上來說 new并沒有任何問題 new是java最基本的部分 真正的問題在于 變化 如果對接口編程 我們可實(shí)現(xiàn)與許多 變化 的隔離 因?yàn)橥ㄟ^多態(tài)機(jī)制 你的代碼對于實(shí)現(xiàn)接口的新類依然適用 但是使用具體類麻煩就來了 因?yàn)樵黾有碌木唧w類時(shí)相應(yīng)代碼可能就必須修改 怎么辦呢 Duckduck newMallardDuck 上面這段代碼所在的模塊與MallardDuck模塊形成了耦合 再回憶我們前面提出的面向?qū)ο笤O(shè)計(jì)的原則 識(shí)別應(yīng)用的變化部分 并將之與固定的部分相分離 區(qū)分變化的部分 下面我們來看一個(gè)例子Pizza店 披薩 PizzaStore類中的一段代碼 訂做pizza PublicClassPizzaStore PizzaorderPizza Pizzapizza newPizza pizza prepare pizza bake pizza cut pizza box returnpizza 真希望這是一個(gè)抽象類或者接口 可惜抽象類或接口都不能被實(shí)例化 而且 我們有許多種pizza 所以我們增加一些代碼 來確定合適的pizza種類 然后進(jìn)行制作 修改后的代碼 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)建相應(yīng)的pizza實(shí)例 并賦值給實(shí)例變量 注意 各種pizza實(shí)現(xiàn)接口Pizza 傳遞pizza的類型給方法orderPizza 每一種pizza子類型都知道其制作方法 由于市場競爭 其他pizza店推出了新產(chǎn)品 我們也得增加 例如VeggiePizza GreekPizza最近不受歡迎 把它從菜單中取消 于是 改 改 改 PizzaorderPizza Stringtype Pizzapizza 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 prepare pizza bake pizza cut pizza box returnpizza 變與不變 變與不變 PizzaorderPizza Stringtype Pizzapizza 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 prepare pizza bake pizza cut pizza box returnpizza 這是變化的部分 隨著Pizza菜單的變化 這部分要跟著不斷地變 這部分是不變的部分 分離 PizzaorderPizza Stringtype Pizzapizza 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 prepare pizza bake pizza cut pizza box returnpizza 把這部分封裝在一個(gè)只管如何創(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的對象 我們將專管制作pizza的對象叫做Pizza工廠 PizzaorderPizza Stringtype Pizzapizza pizza prepare pizza bake pizza cut pizza box returnpizza PizzaFactory 要求制作pizza pizza 這樣 orderPizza方法就成為PizaFactory的客戶 Pizza工廠 SimplePizzaFactory 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的方法 所有客戶都可以用它來實(shí)例化新的pizza對象 這部分代碼就是從orderPizza 方法中抽出來的 和原來的方法一樣 也是通過參數(shù)確定pizza的種類 思考一下 這看來好像我們只是把問題從一個(gè)對象推給了另一個(gè)對象 這樣做有什么好處呢 可以解除客戶代碼 PizzaStore 與具體Pizza的耦合 SimplePizzaFactory可以有許多個(gè)客戶 這樣 當(dāng)實(shí)現(xiàn)改變時(shí)我們只需要修改SimplePizzaFactory 而不需修改眾多的客戶 提高了聚合度 PizzaStore的職責(zé)是使用pizza對象 SimplePizzaFactory的職責(zé)是決定創(chuàng)建什么樣的pizza對象 重寫PizzaStore類 publicclassPizzaStore SimplePizzaFactoryfactory publicPizzaStore SimplePizzaFactoryfactory this factory factory publicPizzaorderPizza Stringtype Pizzapizza pizza factory createPizza type pizza prepare pizza bake pizza cut pizza box returnpizza othermethodshere 簡單工廠模式 Pizza可以是一個(gè)抽象類 也可以是一個(gè)接口 框架 框架的對外接口 簡單工廠模式 有人認(rèn)為這還不是一個(gè)真正的模式 只是一種程序設(shè)計(jì)的習(xí)慣 授權(quán)pizza店 我們的pizza店非常成功 許多人都想開設(shè)我們的授權(quán)加盟店 但是 不同地區(qū)的加盟pizza店可能希望供應(yīng)不同口味的pizza 怎么解決這個(gè)問題呢 解決方法之一 建立不同的工廠 建立不同的工廠 如NYPizzaFactory ChicagoPizzaFactory CaliforniaPizzaFactory 在PizzaStore中包含相應(yīng)工廠的實(shí)例 其代碼類似于 該pizza店提供紐約風(fēng)味的pizzaNYPizzaFactorynyFactory newNYPizzaFactory 建立一個(gè)生產(chǎn)紐約風(fēng)味pizza的工廠PizzaStorenyStore newPizzaStore nyFactory 建立一個(gè)pizza店 引用紐約風(fēng)味pizza的工廠nyStore orderPizza Veggie 生產(chǎn)的是紐約風(fēng)味的pizza 該pizza店提供芝加哥風(fēng)味的pizzaChicagoPizzaFactorychicagoFactory newChicagoPizzaFactory PizzaStorechicagoStore newPizzaStore chicagoFactory chicagoStore orderPizza Veggie 抽象工廠模式 這么多工廠 可以再增加抽象層讓我們一起來設(shè)計(jì) 另一種解決方法 工廠方法模式 思路 改寫的PizzaStore 將createPizza 方法放回到PizzaStore 但是聲明為抽象方法 然后 為每一種地方風(fēng)味創(chuàng)建一個(gè)PizzaStore的子類 改造后的PizzaStore的代碼 publicabstractclassPizzaStore publicPizzaorderPizza Stringtype Pizzapizza createPizza type pizza prepare pizza bake pizza cut pizza box returnpizza abstractPizzacreatePizza Stringtype 在PizzaStore內(nèi)調(diào)用自身的一個(gè)方法來制造pizza 而不是使用一個(gè)factory對象 factory對象成了這里的一個(gè)抽象方法 下面我們需要PizzaStore的各種子類 對應(yīng)不同的地區(qū)風(fēng)味 讓子類做決定 ChicagoPizzaStore createPizza PizzacreatePizza Stringitem if item equals 奶酪 returnnewNYStyleCheesePizza elseif item equals 蔬菜 returnnewNYStyleVeggiePizza elseif item equals 卡姆 returnnewNYStyleClamPizza elseif item equals 辣香腸 returnnewNYStylePepperoniPizza elsereturnnull 討論 為什么說是由子類做決定的 ChicagoPizzaStore createPizza publicabstractclassPizzaStore publicPizzaorderPizza Stringtype Pizzapizza createPizza type pizza prepare pizza bake pizza cut pizza box returnpizza abstractPizzacreatePizza Stringtype 現(xiàn)在讓我們來編寫子類NYPizzaStore ChicagoPizzaStore createPizza publicclassNYPizzaStoreextendsPizzaStore PizzacreatePizza Stringitem if item equals 奶酪 returnnewNYStyleCheesePizza elseif item equals 蔬菜 returnnewNYStyleVeggiePizza elseif item equals 卡姆 returnnewNYStyleClamPizza elseif item equals 辣香腸 returnnewNYStylePepperoniPizza elsereturnnull 怎么編寫子類ChicagoPizzaStore 試試看 聲明工廠方法 publicabstractclassPizzaStore publicPizzaorderPizza Stringtype Pizzapizza createPizza type pizza prepare pizza bake pizza cut pizza box returnpizza abstractPizzacreatePizza Stringtype 實(shí)例化pizza的責(zé)任現(xiàn)在由一個(gè)方法承擔(dān) 該方法相當(dāng)于一個(gè)工廠 我們稱之為工廠方法 PizzaStore的子類用createPizza 方法處理對象的實(shí)例化 聲明工廠方法 abstractPizzacreatePizza Stringtype abstractProductfactoryMethod Stringtype 工廠方法是抽象的 在一個(gè)超類中定義 必須由子類來實(shí)現(xiàn) 工廠方法返回一個(gè)產(chǎn)品 該產(chǎn)品通常在其所在類的方法中定義 如orderPizza 工廠方法通常提供參數(shù) 用以選擇一個(gè)產(chǎn)品的不同品種 工廠方法將客戶 超類中的方法 如PizzaStore中的orderPizza 與具體的產(chǎn)品相隔離 工廠方法怎么工作 假定張三喜歡紐約風(fēng)味的pizza 李四喜歡芝加哥風(fēng)味的pizza 需要相應(yīng)Pizza店的實(shí)例調(diào)用orderPizza 訂購想要的pizza品種createPizza 被調(diào)用 并返回pizza到orderPizza 方法 盡管不知道是什么pizza 但orderPizza 仍知道對它進(jìn)行后續(xù)處理 以張三訂購pizza為例 PizzaStorenyPizzaStore newNYPizzaStore nyPizzaStore orderPizza cheese 在orderPizza 方法中Pizzapizza createPizza cheese 在orderPizza 方法中pizza prepare pizza bake pizza cut pizza box 忘記了產(chǎn)品 pizza 先來個(gè)抽象的 importjava util ArrayList publicabstractclassPizza Stringname Stringdough 生面團(tuán)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 再來個(gè)具體的 publicclassNYStyleCheesePizzaextendsPizza publicNYStyleCheesePizza name NYStyleSauceandCheesePizza dough ThinCrustDough sauce MarinaraSauce toppings add GratedReggianoCheese Marinara mariner s sauceisanItalianredsauceusuallymadewithtomatoes garlic herbs suchasbasil andonion 再來個(gè)另一風(fēng)味的 publicclassChicagoStyleCheesePizzaextendsPizza publicChicagoStyleCheesePizza name ChicagoStyleDeepDishCheesePizza dough ExtraThickCrustDough sauce PlumTomatoSauce toppings add ShreddedMozzarellaCheese voidcut System out println Cuttingthepizzaintosquareslices 測試主類 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 工廠方法模式中的類 創(chuàng)建者類TheCreatorclasses ChicagoPizzaStore createPizza Abstractcreator Concretecreators 工廠方法模式中的類 產(chǎn)品類TheProductclasses Abstractproduct Concreteproducts 工廠方法模式的正式定義 在類中定義一個(gè)用于創(chuàng)建對象的接口方法 讓其子類決定實(shí)例化哪一個(gè)類 通過這種做法 使得工廠方法的客戶 工廠方法的使用者 不必了解具體應(yīng)該實(shí)例化哪一個(gè)類 如 pizza pizzaStore orderPizza cheese 生產(chǎn)出來的匹薩是紐約風(fēng)味的還是芝加哥風(fēng)味的取決于pizzaStore引用的是哪個(gè)PizzaStore的子類 工廠方法模式的結(jié)構(gòu) 總結(jié) FactoryMethod模式 意圖定義一個(gè)用于創(chuàng)建對象的接口 讓子類決定實(shí)例化哪一個(gè)類 工廠方法模式讓一個(gè)類的實(shí)例化延遲到其子類 使得對象的創(chuàng)建與對象的使用分離開來 別名虛擬構(gòu)造器 工廠方法模式的優(yōu)點(diǎn)與適用場景 優(yōu)點(diǎn)讓用戶代碼與特定類Product的子類ConcretProduct的代碼解耦 用戶不必知道它所使用的對象是怎么創(chuàng)建的 只需要知道這些對象的用法即可 適用場景希望讓用戶使用某些類 但不希望與這些類形成耦合 用new 用戶需要一個(gè)類的子類的實(shí)例 但不知道該類有哪些子類可用 工廠方法模式的好處 用戶程序只需要和這些類打交道 總結(jié) FactoryMethod 參與者 Product document 定義工廠方法所創(chuàng)建對象的接口 ConcreteProduct mydocument 實(shí)現(xiàn)product接口 Creator application 聲明工廠方法可以調(diào)用工廠方法以創(chuàng)建一個(gè)product對象ConcreteCreator MyApplication 重新定義工廠方法 以返回一個(gè)ConcreteProduct實(shí)例 工廠方法的經(jīng)典范例 java迭代器 Collection接口中定義了iterator 方法 所有的集合類都實(shí)現(xiàn)了這個(gè)方法 iterator 方法就是一個(gè)工廠方法 其使用者不必了解需要實(shí)例化哪個(gè)類 importjava util publicclassShowIterator publicstaticvoidmain String args Listlist Arrays asList newString fountaun rocket tree Iteratoriter list iterator while iter hasNext System out println iter next 抽象工廠解決的問題 抽象工廠模式是避免必須修改所有new調(diào)用問題的一個(gè)有效策略 抽象工廠的所有具體化有一個(gè)共同的主題 使用工廠來創(chuàng)建實(shí)現(xiàn)了已知接口 但類型尚不明確的對象 抽象工廠一般與單例模式聯(lián)系在一起 由單例模式獲得抽象工廠 由抽象工廠制造實(shí)際類型未知的產(chǎn)品對象 經(jīng)典例句Imageim Toolkit getDefaultToolkit createImage i 每次調(diào)用getDefaultToolkit 方法得到的是同一個(gè)Toolkit實(shí)例 createImage 是Toolkit的一個(gè)方法 習(xí)題 上機(jī)完成 某連鎖超市為留住顧客 決定發(fā)行會(huì)員卡 會(huì)員卡分為金卡 銀卡 普通卡等多種類型 卡的類型可能還會(huì)增加 不論是什么卡 其編號(hào)都是統(tǒng)一編制的 即使用同一個(gè)編號(hào)序列 某軟件公司承接了該項(xiàng)目 設(shè)計(jì)人員覺得應(yīng)該將系統(tǒng)設(shè)計(jì)的具有一定的通用性 不僅可以較方便的應(yīng)對該連鎖店的需求變化 增減卡的類型 而且可以較容易的修改擴(kuò)展 為其他公司提供發(fā)卡 卡的風(fēng)格可能不同 服務(wù) 假定你是該軟件公司的設(shè)計(jì)師 請你運(yùn)用學(xué)過的設(shè)計(jì)模式設(shè)計(jì)該系統(tǒng)的架構(gòu) 編寫實(shí)驗(yàn)報(bào)告 要求畫出相應(yīng)的類圖 提供示意性java源程序 實(shí)驗(yàn)報(bào)告發(fā)至sam84149- 1.請仔細(xì)閱讀文檔,確保文檔完整性,對于不預(yù)覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- java 工廠 設(shè)計(jì) 模式
鏈接地址:http://ioszen.com/p-7399396.html