Head First设计模式读书笔记——策略模式
問題描述:
?????? 目前的任務是實現一個FPS類游戲的各種角色(友軍、敵軍、平民和狗、貓、鴨子等動物)以及他們的各種行為(攻擊、游泳等)。
設計方案一
?????? 很簡單,只要實現一個角色超類,將角色的各種行為放入超類中,其他具體角色都繼承次角色超類就可以了。類圖如下所示(由于不同的角色有不同的外觀,所以display設定為抽象方法,由子類自己實現)。
?????? 現在想想,這個設計有什么潛在的問題?對了,游戲開發完成后,你在享受游戲的樂趣的同時可能會發現竟然有一只貓在游泳,還有一只鴨子在向友軍攻擊...。這些是有悖常理,絕對不允許出現的。也許會有人想到一種解決方案,就是在子類中覆蓋父類中相應的方法。但是這樣一來,如果系統需要加入新的角色,程序員必須跟蹤并可能覆蓋fight和swim方法,永無止境的噩夢。必須更改設計方案。
設計方案二
?????? 針對上一個方案出現的問題,首先將會變化的行為(fight和swim)抽出來,各自放入單獨的接口fightAction和swimAction中,只有具有此類行為的角色才會實現相應的接口。設計圖如下:
?????? 稍稍動動腦筋就會發現,這種設計方案其實超傻。如果有成千上萬種角色,就意味著程序員要重復編寫成千上萬次同樣的代碼。完全消除了代碼復用的優勢,幾乎可以榮登史上最傻方案榜了。毫不猶豫,淘汰,必須更改方案。
設計方案三
?????? 在上一篇文章”面向對象設計原則”中的第一個原則是“封裝變化”,這個原則可以理解為:“找出應用程序中需要變化的部分,把它們獨立出來,不要和那些不需要變化的代碼混在一起,以便以后可以輕易的改動或擴充此部分而不至影響到其他部分。”基于此,把角色的行為從角色中抽離出來。
?????? 為了實現“封裝變化”,首先建立兩組類,其中一個關乎fight行為的,另一個是關乎swim行為的,各自實現各自的行為,并將該兩組類完全脫離角色類。
?????? 以上一切工作都是為了使得程序更具有彈性,易于擴展。所以,當然不能讓子類來實現設定行為的方法,必須放在父類中。
?????? ”面向對象設計原則”中的第三個原則是“針對接口編程,而不是針對實現編程”,注意,此處講到的接口并不是特指某個C#或java的接口,而是泛指實現某個超類性(類或接口)的某個方法。在此設計方案中利用接口代表行為,fight行為用FightAction接口代表,swim行為用SwimAction接口代表,這樣角色本身不會負責實現某個行為,而是由專門的“行為類”(實現行為接口的類)來負責。設計方案如下圖所示:
?????? 父類Character中用performFight和performSwim方法代替了方案一和方案二中的fight和swim方法。在performFight方法和performSwim方法中調用fightAction和swimAction中的fight和swim方法實現角色的行為。而每一個角色子類的fightAction和swimAction成員是在角色本身實例化的時候指定的。利用此方案實現的系統,決不會出現具有攻擊行為的鴨子和會游泳的貓,同時也保證了系統的可擴展性,有新的行為加入的時候(如fightWithKnife)只需要添加一個新的行為類即可以實現。程序員甚至可以在父類中添加一個setFightAction(FightAction fightAction)或setSwimAction(SwimAction swimAction)方法來實現每一個角色在運行的時候動態的改變行為(如用槍攻擊改為用刀攻擊)。
總結
?????? 以上陳述的“設計方案三”利用的既是策略模式,有心的你也許會發現,該方案同樣遵循了”面向對象設計原則”中的第二個原則是“多用組合,少用繼承”。每一個角色都具有一個fightAction和swimAction用于委托處理fight行為和swim行為,這就是組合。“組合”不同于“繼承”之處在于角色的行為不是繼承來的,而是由行為對象組合而來。
?????? 引用策略模式的官方定義:“策略模式定義了算法族,分別封裝起來,讓它們直之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶”。不難發現,該模式主要適用于不同客戶(角色)使用不同策略(行為),并且策略本身將來可能通過不同方式實現,需要對客戶隱藏具體策略的實現細節,完全獨立的情況。策略模式提供了一種替代繼承的方法,既保持了繼承的優點(代碼復用),同時也比繼承更加靈活(算法獨立,可任意擴展)。該模式還避免了多重條件語句的出現,使系統更易于擴展和維護。
轉載于:https://www.cnblogs.com/NeeoMeng/articles/1119250.html
總結
以上是生活随笔為你收集整理的Head First设计模式读书笔记——策略模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ogre plugin for 3dma
- 下一篇: 如何在webservice中取得sess