java_策略模式_第1頁(yè)
java_策略模式_第2頁(yè)
java_策略模式_第3頁(yè)
java_策略模式_第4頁(yè)
java_策略模式_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、當(dāng)我們掌握了Java 的語(yǔ)法,當(dāng)我們了解了面向?qū)ο蟮姆庋b、繼承、多態(tài)等特性,當(dāng)我們可以用Swing 、Servlet 、JSP技術(shù)構(gòu)建桌面以及 Web 應(yīng)用,不意味著我們可以寫出面向?qū)ο蟮某绦?,不意味著我們可以很好的?shí)現(xiàn)代碼復(fù)用,彈性維護(hù),不意味著我們可以實(shí)現(xiàn)在維護(hù)、擴(kuò)展基礎(chǔ)上的代碼復(fù)用。一把刀,可以使你制敵于無(wú)形而于江湖揚(yáng)名,也可以只是一把利刃而使你切菜平靜。Java,就是這把刀,它的威力取決于你使用的方式。當(dāng)我們陷入無(wú)盡無(wú)止重復(fù)代碼的泥沼,當(dāng)我們面臨牽一發(fā)而動(dòng)全身的維護(hù)惡夢(mèng), 你應(yīng)該想起 “設(shè)計(jì)模式”這個(gè)行動(dòng)秘笈。面向?qū)ο蟮木x,看似平淡,其實(shí)要經(jīng)過(guò)艱苦實(shí)踐才能成功。而構(gòu)造OO 系統(tǒng)的隱含

2、經(jīng)驗(yàn)于是被前人搜集而成并冠以“設(shè)計(jì)模式 ”之名。我們應(yīng)該在編碼行動(dòng)初始就攜帶以它。接下來(lái),讓我們步 “四人組 ”先行者之后,用中國(guó)文字、用實(shí)際案例領(lǐng)略模式于我們代碼煥然一新的改變:設(shè)計(jì)模式解讀之一:策略模式1. 模式定義把會(huì)變化的內(nèi)容取出并封裝起來(lái),以便以后可以輕易地改動(dòng)或擴(kuò)充部分,而不影響不需要變化的其他部分;2. 問(wèn)題緣起當(dāng)涉及至代碼維護(hù)時(shí),為了復(fù)用目的而使用繼承,結(jié)局并不完美。對(duì)父類的修改,會(huì)影響到子類型。在超類中增加的方法,會(huì)導(dǎo)致子類型有該方法,甚至連那些不該具備該方法的子類型也無(wú)法免除。示例,一個(gè)鴨子類型:public abstract class Duck / 所有的鴨子均會(huì)叫以及

3、游泳,所以父類中處理這部分代碼public void quack() System.out.println(Quack);public void swim() System.out.println(All ducks float, even decoys.);/ 因?yàn)槊糠N鴨子的外觀是不同的,所以父類中該方法是抽象的,由子類型自己完成。public abstract void display();public class MallardDuck extends Duck / 野鴨外觀顯示為綠頭public void display() System.out.println(Green head.

4、);public class RedHeadDuck extends Duck / 紅頭鴨顯示為紅頭public void display() System.out.println(Red head.);public class RubberDuck extends Duck / 橡皮鴨叫聲為吱吱叫,所以重寫父類以改寫行為public void quack() System.out.println(Squeak);/ 橡皮鴨顯示為黃頭public void display() System.out.println(Yellow head.);上述代碼,初始實(shí)現(xiàn)得非常好。現(xiàn)在我們?nèi)绻o Duck

5、.java 中加入 fly() 方法的話,那么在子類型中均有了該方法, 于是我們看到了 會(huì)飛的橡皮鴨子, 你看過(guò)嗎?當(dāng)然, 我們可以在子類中通過(guò)空實(shí)現(xiàn)重寫該方法以解決該方法對(duì)于子類型的影響。但是父類中再增加其它的方法呢?通過(guò)繼承在父類中提供行為,會(huì)導(dǎo)致以下缺點(diǎn):a. 代碼在多個(gè)子類中重復(fù);b. 運(yùn)行時(shí)的行為不容易改變;c. 改變會(huì)牽一發(fā)動(dòng)全身,造成部分子類型不想要的改變;好啦,還是剛才鴨子的例子,你也許想到使用接口,將飛的行為、叫的行為定義為接口,然后讓Duck的各種子類型實(shí)現(xiàn)這些接口。這時(shí)侯代碼類似于:public abstract class Duck / 將變化的行為fly()以及 qu

6、ake() 從 Duck 類中分離出去定義形成接口,有需求的子類中自行去實(shí)現(xiàn)public void swim() System.out.println(All ducks float, even decoys.);public abstract void display();/ 變化的 fly() 行為定義形成的接口public interface FlyBehavior void fly();/ 變化的 quack() 行為定義形成的接口public interface QuackBehavior void quack();/ 野鴨子會(huì)飛以及叫,所以實(shí)現(xiàn)接口FlyBehavior, Quac

7、kBehaviorpublic class MallardDuck extends Duck implements FlyBehavior, QuackBehavior public void display() System.out.println(Green head.);public void fly() System.out.println(Fly.);public void quack() System.out.println(Quack.);/ 紅頭鴨子會(huì)飛以及叫,所以也實(shí)現(xiàn)接口FlyBehavior, QuackBehaviorpublic class RedHeadDuck e

8、xtends Duck implements FlyBehavior, QuackBehavior public void display() System.out.println(Red head.);public void fly() System.out.println(Fly.);public void quack() System.out.println(Quack.);/ 橡皮鴨不會(huì)飛,但會(huì)吱吱叫,所以只實(shí)現(xiàn)接口QuackBehaviorpublic class RubberDuck extends Duck implements QuackBehavior/ 橡皮鴨叫聲為吱吱叫p

9、ublic void quack() System.out.println(Squeak);/ 橡皮鴨顯示為黃頭public void display() System.out.println(Yellow head.);上述代碼雖然解決了一部分問(wèn)題, 讓子類型可以有選擇地提供一些行為 (例如 fly() 方法將不會(huì)出現(xiàn)在橡皮鴨中 ). 但我們也看到, 野鴨子 MallardDuck.java 和紅頭鴨子 RedHeadDuck.java 的一些相同行為代碼不能得到重復(fù)使用。很大程度上這是從一個(gè)火坑跳到另一個(gè)火坑。在一段程序之后,讓我們從細(xì)節(jié)中跳出來(lái),關(guān)注一些共性問(wèn)題。不管使用什么語(yǔ)言,構(gòu)建什

10、么應(yīng)用,在軟件開(kāi)發(fā)上,一直伴隨著的不變的真理是:需要一直在變化。不管當(dāng)初軟件設(shè)計(jì)得多好,一段時(shí)間之后,總是需要成長(zhǎng)與改變,否則軟件就會(huì)死亡。我們知道,繼承在某種程度上可以實(shí)現(xiàn)代碼重用,但是父類( 例如鴨子類Duck) 的行為在子類型中是不斷變化的,讓所有子類型都有這些行為是不恰當(dāng)?shù)?。我們可以將這些行為定義為接口,讓Duck 的各種子類型去實(shí)現(xiàn),但接口不具有實(shí)現(xiàn)代碼,所以實(shí)現(xiàn)接口無(wú)法達(dá)到代碼復(fù)用。這意味著,當(dāng)我們需要修改某個(gè)行為,必須往下追蹤并在每一個(gè)定義此行為的類中修改它,一不小心,會(huì)造成新的錯(cuò)誤。設(shè)計(jì)原則:把應(yīng)用中變化的地方獨(dú)立出來(lái),不要和那些不需要變化的代碼混在一起。這樣代碼變化引起的不經(jīng)

11、意后果變少,系統(tǒng)變得更有彈性。按照上述設(shè)計(jì)原則,我們重新審視之前的Duck 代碼。1) 分開(kāi)變化的內(nèi)容和不變的內(nèi)容Duck 類中的行為Duck 類中的行為fly(), quack(),每個(gè)子類型可能有自己特有的表現(xiàn),這就是所謂的變化的內(nèi)容。swim()每個(gè)子類型的表現(xiàn)均相同,這就是所謂不變的內(nèi)容。我們將變化的內(nèi)容從 Duck() 類中剝離出來(lái)單獨(dú)定義形成接口以及一系列的實(shí)現(xiàn)類型。將變化的內(nèi)容定義形成接口可實(shí)現(xiàn)變化內(nèi)容和不變內(nèi)容的剝離。其實(shí)現(xiàn)類型可實(shí)現(xiàn)變化內(nèi)容的重用。這些實(shí)現(xiàn)類并非Duck.java 的子類型,而是專門的一組實(shí)現(xiàn)類,稱之為 行為類 。由行為類而不是Duck.java的子類型來(lái)實(shí)現(xiàn)

12、接口。這樣,才能保證變化的行為獨(dú)立于不變的內(nèi)容。于是我們有:變化的內(nèi)容:/ 變化的 fly() 行為定義形成的接口public interface FlyBehavior void fly();/ 變化的 fly() 行為的實(shí)現(xiàn)類之一public class FlyWithWings implements FlyBehavior public void fly() System.out.println(Im flying.);/ 變化的 fly() 行為的實(shí)現(xiàn)類之二public class FlyNoWay implements FlyBehavior public void fly() Sy

13、stem.out.println(I cant fly.);-/ 變化的 quack() 行為定義形成的接口public interface QuackBehavior void quack();/ 變化的 quack() 行為實(shí)現(xiàn)類之一public class Quack implements QuackBehavior public void quack() System.out.println(Quack);/ 變化的 quack() 行為實(shí)現(xiàn)類之二public class Squeak implements QuackBehavior public void quack() Syste

14、m.out.println(Squeak.);/ 變化的 quack() 行為實(shí)現(xiàn)類之三public class MuteQuack implements QuackBehavior public void quack() System.out.println();通過(guò)以上設(shè)計(jì),fly() 行為以及quack() 行為已經(jīng)和Duck.java 沒(méi)有什么關(guān)系,可以充分得到復(fù)用。而且我們很容易增加新的行為 , 既不影響現(xiàn)有的行為,也不影響在面向?qū)ο笾行袨椴皇求w現(xiàn)為方法嗎?為什么現(xiàn)在被定義形成類Duck.java 。但是,大家可能有個(gè)疑問(wèn),就是(例如 Squeak.java) ?在 OO 中,類代表

15、的 東西 一般是既有狀態(tài)(實(shí)例變量)又有方法。只是在本例中碰巧 東西 是個(gè)行為。既使是行為,也有屬性及方法,例如飛行行為,也需要一些屬性記錄飛行的狀態(tài),如飛行高度、速度等。2) 整合變化的內(nèi)容和不變的內(nèi)容Duck.java 將 fly() 以及 quack() 的行為委托給行為類處理。不變的內(nèi)容:public abstract class Duck / 將行為類聲明為接口類型,降低對(duì)行為實(shí)現(xiàn)類型的依賴FlyBehavior flyBehavior;QuackBehavior quackBehavior;public void performFly() / 不自行處理fly() 行為,而是委拖給

16、引用flyBehavior 所指向的行為對(duì)象flyBehavior.fly();public void performQuack() quackBehavior.quack();public void swim() System.out.println(All ducks float, even decoys.);public abstract void display();Duck.java 不關(guān)心如何進(jìn)行fly() 以及 quack(),這些細(xì)節(jié)交由具體的行為類完成。public class MallardDuck extends Duckpublic MallardDuck() flyB

17、ehavior=new FlyWithWings();quackBehavior=new Quack();public void display() System.out.println(Green head.);測(cè)試類:public class DuckTest public static void main(String args) Duck duck=new MallardDuck();duck.performFly();duck.performQuack();在 Duck.java 子類型 MallardDuck.java 的構(gòu)造方法中,直接實(shí)例化行為類型, 在編譯的時(shí)侯便指定具體行為

18、類型。當(dāng)然,我們可以:1) 我們可以通過(guò)工廠模式或其它模式進(jìn)一步解藕( 可參考后續(xù)模式講解 );2) 或做到在運(yùn)行時(shí)動(dòng)態(tài)地改變行為。3) 動(dòng)態(tài)設(shè)定行為在父類 Duck.java 中增加設(shè)定行為類型的 setter 方法,接受行為類型對(duì)象的參數(shù)傳入。為了降藕,行為參數(shù)被聲明為接口類型。這樣,既便在運(yùn)行時(shí),也可以通過(guò)調(diào)用這二個(gè)方法以改變行為。public abstract class Duck / 在剛才 Duck.java 中加入以下二個(gè)方法。public void setFlyBehavior(FlyBehavior flyBehavior) this.flyBehavior=flyBehavior;public void setQuackBehavior(QuackBehavior quackBehavior) this.quackBehavior=quackBehavior;/ 其它方法同,省略 .測(cè)試類:public class DuckTest public static voi

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論