版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、1,第六章 策略模式,模擬鴨子的簡(jiǎn)單應(yīng)用 Joe(喬)上班的公司做了一套相當(dāng)成功的模擬鴨子游戲SimUDuck,游戲中出現(xiàn)各種鴨子, 一邊游泳戲水, 一邊呱呱叫。此系統(tǒng)的內(nèi)部設(shè)計(jì)使用了標(biāo)準(zhǔn)的OO技術(shù),設(shè)計(jì)了一個(gè)鴨子超類(Superclass),并讓各種鴨子繼承此超類。,2,Duck是抽象類。,3,類之間畫箭頭 繼承就畫成這樣(extend)。 實(shí)現(xiàn)接口就畫成這樣(implement)。 “有一個(gè)(has a)”關(guān)系就畫成這樣。,4,讓鴨子能飛 去年,公司的競(jìng)爭(zhēng)壓力加劇,公司主管認(rèn)為該是創(chuàng)新 的時(shí)候了。主管認(rèn)為, 此模擬程序需要會(huì)飛的鴨子, 將競(jìng) 爭(zhēng)者拋在后頭。,當(dāng)然,在這個(gè)時(shí)候,Joe的經(jīng) 理
2、拍胸脯告訴主管 們,Joe只需要一個(gè) 星期就可以搞定。 “Joe畢竟是一個(gè)OO 程序員.這有什么 困難?”,5,6,問題發(fā)生 橡皮鴨子能飛了。,當(dāng)涉及“維護(hù)”時(shí),為了“復(fù)用”目的使用繼承,結(jié)局并不完美。,7,8,效果怎么樣?,木頭假鴨,9,改進(jìn)繼承 Joe認(rèn)識(shí)到繼承可能不是一個(gè)好的解決方法, 因?yàn)樗麆倓偰玫絹碜灾鞴艿膫渫洠?希望以后每六個(gè)月更新產(chǎn)品(至于更新的方法,他們還沒想到)。Joe知道規(guī)格會(huì)常常改變, 每當(dāng)有新的鴨子子類出現(xiàn),他就要被迫檢視并可能需要覆蓋fly()和quark(). 這簡(jiǎn)直是無窮盡的惡夢(mèng)。所以,他需要一個(gè)更清晰的方法,讓某些(而不是全部)鴨子類型可飛或可叫。,10,11
3、,這個(gè)設(shè)計(jì)如何?,12,改進(jìn)后的 繼承分析,13,其實(shí),并非所有的鴨子子類都具有飛行和呱呱叫的行為,所以繼承并不是適當(dāng)?shù)慕鉀Q方式。雖然Flyable 與Quackable可以解決一部分的問題(不會(huì)再有會(huì)飛的橡皮鴨),但是卻造成代碼無法復(fù)用,這只能算是從一個(gè)惡夢(mèng)跳進(jìn)另一個(gè)惡夢(mèng)。甚至,在會(huì)飛的鴨子中,飛行的 動(dòng)作可能還有多種變化,14,現(xiàn)在我們知道使用繼承有一些缺失, 因?yàn)楦淖凐喿拥男袨闀?huì)影響所有種類的鴨子,而這并不恰當(dāng)。Flyable與Quackable接口一開始似乎還挺不錯(cuò), 解決了問題(只有會(huì)飛的鴨子才繼承Flyable),但是Java的接口不具有實(shí)現(xiàn)代碼,所以繼承接口無法達(dá)到代碼的復(fù)用。這
4、意味著:無論何時(shí)你需要修改某個(gè)行為, 你被迫得往下追蹤并修改每一個(gè)有定義此行為的類,一不小心,可能造成新的錯(cuò)誤。,15,第一個(gè)設(shè)計(jì)原則,這樣的概念很簡(jiǎn)單,幾乎是每個(gè)設(shè)計(jì)模式背后的 精神所在。所有的模式都提供了一套方法讓系統(tǒng)中的 某部分改變不會(huì)影響其它部分。,16,分開變化和不變的部分 為了要分開變化和不會(huì)變化的部分,我們準(zhǔn)備建立兩組類,一個(gè)是fly相關(guān)的,一個(gè)是quack相關(guān)的,每一組類將實(shí)現(xiàn)各自的動(dòng)作。比方說,我們可能有一個(gè)類實(shí)現(xiàn)“呱呱叫”,另一個(gè)類實(shí)現(xiàn)“吱吱叫”,另一個(gè)類實(shí)現(xiàn)“安靜”。,17,18,設(shè)計(jì)鴨子行為 我們利用接口代表每個(gè)行為,比方說, FlyBehavior與QuackBeha
5、vior,而行為的每個(gè)實(shí)現(xiàn)都必須實(shí)現(xiàn)這些接口之一。所以這次鴨子類不會(huì)負(fù)責(zé)實(shí)現(xiàn)Flying與Quacking接口,而是由其它類專門實(shí)現(xiàn)FlyBehavior與QuackBehavior, 這就稱為“行為”類。由行為類實(shí)現(xiàn)行為接口,而不是由Duck類實(shí)現(xiàn)行為接口。,19,這樣的作法迥異于以往,以前的作法是:行為是繼承 自Duck超類的具體實(shí)現(xiàn)而來,或是繼承某個(gè)接口并由子類 自行實(shí)現(xiàn)而來。這兩種作法都是依賴于“實(shí)現(xiàn)”,我們被實(shí)現(xiàn) 綁得死死的,沒辦法更改行為(除非寫更多代碼)。,20,接著看看第二個(gè)設(shè)計(jì)原則:,關(guān)于接口編程和實(shí)現(xiàn)編程: 假設(shè)有一個(gè)抽象類Animal,有兩個(gè)具體 的實(shí)現(xiàn)(Dog與Cat)
6、繼承自Animal。,21,22,針對(duì)實(shí)現(xiàn)編程作法如下: Dog d = new Dog(); d.bark(); 針對(duì)接口/超類型編程作法如下: Animal animal = new Dog(); animal.makeSound(); 子類型實(shí)例化的動(dòng)作是“在運(yùn)行時(shí)才指定具體實(shí)現(xiàn)的對(duì)象”。 a = getAnimal(); a.makeSound();,23,實(shí)現(xiàn)鴨子的行為,24,25,集成鴨子的行為 鴨子現(xiàn)在會(huì)將飛行和呱呱叫的動(dòng)作,委托(delegate)別 人處理,而不是使用定義在自己類(或子類)內(nèi)的方法。 首先,在鴨子中加入兩個(gè)實(shí)例變量, 分別為FlyBehavior 與Quack
7、Behavior,聲明為接口類型(而不是具體類實(shí)現(xiàn)類 型),每個(gè)變量會(huì)利用多態(tài)的方式在運(yùn)行時(shí)引用正確的行 為類型(例如:FlyWithWings、Squeak . . . 等)。 我們也必須將Duck類與其所有子類中的fly() 與quack( ) 移 除,因?yàn)檫@些行為已經(jīng)被搬移到FlyBehavior與 QuackBehavior類中了。我們用performFly()和 performQuack()取代Duck類中的fly()與quack()。,26,27,現(xiàn)在,我們來實(shí)現(xiàn)performQuack(): public class Duck QuackBehavior quackBehavio
8、r; / 還有更多 public void performQuack() quackBehavior.quack(); ,每只鴨子都引用實(shí)現(xiàn)QuackBehavior接口的對(duì)象。,鴨子將呱呱叫行為委托給quackBehavior引用的對(duì)象。,28, 下面設(shè)定FlyBehavior和QuackBehavior的實(shí)例變量 (MallardDuck類為例)。 public class MallardDuck extends Duck public MallardDuck() quackBehavior = new Quack(); flyBehavior = new FlyWithWings();
9、public void display() System.out.println(Im a real Mallard duck); ,Quack類處理呱呱叫。,FlyWithWings作為FlyBehavior 類型。,MallardDuck從Duck 繼承,具有flyBehavior 和quackBehavior 實(shí)例變量。,29,測(cè)試Duck代碼 輸入下面的Duck類(Duck.java )以及前面的MallardDuck 類(MallardDuck.java),并編譯之。 public abstract class Duck FlyBehavior flyBehavior; QuackB
10、ehavior quackBehavior; public Duck() abstract void display(); public void performFly() flyBehavior.fly(); public void performQuack() quackBehavior.quack(); public void swim() System.out.println(All ducks float, even decoys!); ,為行為接口類型聲明兩個(gè)引用變量,所有鴨子子類都繼承它們。,委托給行為類,30, 輸入FlyBehavior接口(FlyBehavior.java)
11、與兩個(gè)行為實(shí) 現(xiàn)類(FlyWithWings.java和FlyNoWay),并編譯之。 public interface FlyBehavior public void fly(); public class FlyWithWings implements FlyBehavior public void fly() System.out.println(Im flying!); public class FlyNoWay implements FlyBehavior public void fly() System.out.println(I cant fly); ,所有飛行行為必須實(shí)現(xiàn)的接口
12、。,不會(huì)飛的鴨子,真會(huì)飛的鴨子,31, 輸入QuackBehavior接口(QuackBehavior.java)及其三個(gè)實(shí)現(xiàn) 類(Quack.java、MuteQuack.java、Squeak.java),并編譯之。 public interface QuackBehavior public void quack(); public class Quack implements QuackBehavior public void quack() System.out.println(Quack); public class MuteQuack implements QuackBehavio
13、r public void quack() System.out.println(); public class Squeak implements QuackBehavior public void quack() System.out.println(Squeak); ,32, 輸入并編譯測(cè)試類(MiniDuckSimulator.java) public class MiniDuckSimulator public static void main(String args) Duckmallard = new MallardDuck(); mallard.performQuack();
14、mallard.performFly(); ,調(diào)用MallardDuck繼承來的perform方法,進(jìn)而將綠頭鴨的行為委托給quack和fly的行為類來處理。,33, 運(yùn)行代碼!,34,設(shè)定行為 假設(shè)我們想在鴨子子類透過設(shè)定方法(setter method)設(shè) 定鴨子的行為,而不是在鴨子的構(gòu)造器內(nèi)實(shí)例化。 在Duck類中,加入兩個(gè)新方法: public void setFlyBehavior (FlyBehavior fb) flyBehavior = fb; public void setQuackBehavior(QuackBehavior qb) quackBehavior = qb;
15、,35,制造一個(gè)新的鴨子類型:模型鴨(ModelDuck.java) public class ModelDuck extends Duck public ModelDuck() flyBehavior = new FlyNoWay(); quackBehavior = new Quack(); public void display() System.out.println(Im a model duck); ,一開始模型鴨不會(huì)飛。,36, 建立一個(gè)新的FlyBehavior類型(FlyRockedPowered.java),public class FlyRocketPowered imp
16、lements FlyBehavior public void fly() System.out.println(Im flying with a rocket); ,建立一個(gè)火箭動(dòng)力的飛行行為。,37, 改變測(cè)試類 (MiniDuckSimulator.java),加上模型 鴨,讓模型鴨具有火箭動(dòng)力。,public class MiniDuckSimulator public static void main(String args) Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); Duck model = new ModelDuck(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered(); model.performFly(); ,改變前,設(shè)置火箭動(dòng)力。,改變后,38, 運(yùn)行,改變前,改變后,39,封裝格局 所有鴨子從Duck繼承,飛行行為實(shí)現(xiàn)FlyBehavior 接口,呱呱叫行為實(shí)現(xiàn)QuackBehavior接口。,40,“有一個(gè)”(has a)可能比“是一個(gè)”(is a)更好 有一個(gè)關(guān)系相當(dāng)有趣: 每一鴨子都有一個(gè)FlyBehavior且 有一個(gè)QuackBehav
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025乳房再造加速康復(fù)外科中國專家共識(shí)(2022版)解讀課件
- 返鄉(xiāng)學(xué)生網(wǎng)絡(luò)安全培訓(xùn)課件
- 施工沖刺階段保通方案
- 車險(xiǎn)培訓(xùn)課件制作
- 車隊(duì)安全駕駛培訓(xùn)記錄課件
- 某醫(yī)藥靜脈輸液知識(shí)試題含答案
- 車間領(lǐng)班安全培訓(xùn)課件
- 酒店客房用品更換與補(bǔ)給制度
- 酒店消防安全巡查制度
- 2025年八級(jí)班主任工作總結(jié)(2篇)
- 1輸變電工程施工質(zhì)量驗(yàn)收統(tǒng)一表式(線路工程)-2024年版
- 陜西省建筑場(chǎng)地墓坑探查與處理技術(shù)規(guī)程
- 2022-2023學(xué)年四川省樂山市市中區(qū)外研版(三起)六年級(jí)上冊(cè)期末測(cè)試英語試卷(含聽力音頻)
- 滕州菜煎餅創(chuàng)新創(chuàng)業(yè)計(jì)劃書
- 2024北京朝陽區(qū)初一(上)期末道法試卷及答案
- 假體隆胸后查房課件
- 送貨單格式模板
- GB/T 42430-2023血液、尿液中乙醇、甲醇、正丙醇、丙酮、異丙醇和正丁醇檢驗(yàn)
- 關(guān)于地方儲(chǔ)備糧輪換業(yè)務(wù)會(huì)計(jì)核算處理辦法的探討
- 上海農(nóng)貿(mào)場(chǎng)病媒生物防制工作標(biāo)準(zhǔn)
- YY 0334-2002硅橡膠外科植入物通用要求
評(píng)論
0/150
提交評(píng)論