[菜鳥的設計模式之旅]策略模式

策略模式

定義

什麼是策略模式?定義了算法族,分別封裝起來,讓它們之間能夠互相替換,此模式讓算法的變化獨立於使用算法的客戶。

個人理解就是:好比咱們接下來要說到的鴨子案例,有的鴨子能夠飛,而飛又分爲不少種,飛很高,飛得很低各類,咱們就會把飛這個行爲定義爲接口,而後再分別去實現,而咱們的鴨子只須要注入「飛」的行爲,就能夠去飛,至於怎麼飛,鴨子不用去管,這也算是面向接口編程吧。固然除了飛,還有不少行爲,咱們均可以把這些行爲抽成接口,而後再具體實現,讓鴨子有接口類型的變量,就有了對應的行爲啦~固然鴨子也分不少種,好比橡皮泥鴨子,這是確定不能飛行的,那麼咱們就不須要去給他設置飛行實現就行了。很是的靈活,能夠面對各類變化,  好比鴨子受傷了,不能飛了,那就修改下鴨子注入的飛行行爲的實現,再好比鴨子又多了一種技能,能呱呱叫了,那就再寫一個呱呱叫接口,至於怎麼呱呱叫,讓具體的實現去解決。html

 

 

接下來我來粘貼一下《Head First 設計模式》上的案例即鴨子算法

舉例

首先是鴨子抽象類:編程

我定義了一個FlyBehavior類型的變量,這個FlyBehavior是一個飛行行爲的接口,這就意味着鴨子有了飛行行爲設計模式

至於怎麼飛,咱們不須要考慮,交給飛行的實現去飛,也就是performFly(),同時還有一個setFlyBehavior(),這個方法就意味着,鴨子可以在運行時動態的修改本身飛行的實現,好比原本是「飛的很高」,後來鴨子年紀大了,飛不了很高了,那就用這個方法修改一下本身的飛行實現。好比duck.setFlyBehavior(new FlyLow()); app

package object; import behaviour.FlyBehavior; public abstract class Duck { protected FlyBehavior flyBehavior; public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public abstract void swim(); public abstract void display(); public void performFly(){ flyBehavior.fly(); } }

有了抽象類確定要有實現類呀,這就奉上香噴噴的"馴化野鴨」ide

flyBehavior的變量是從父類Duck繼承過來的,而FlyWithWings是實現了FlyBehavior接口的"用翅膀飛行」,MallardDuck的構造函數就意味着,"馴化野鴨"對飛行行爲的描述默認是「用翅膀飛行」,固然若是想改變它的飛行行爲,那麼只須要用剛剛提到的父類中的setFlyBehavior()方法就行了函數

package object.concreteobject; import behaviour.FlyWithWings; import object.Duck; public class MallardDuck extends Duck{ public MallardDuck(){ flyBehavior = new FlyWithWings(); } @Override public void swim() { // TODO Auto-generated method stub
        System.out.println("I'm swimming!"); } @Override public void display() { System.out.println("I'm a real Mallard duck"); } }

固然,既然是粘貼代碼,就必定要粘貼全,這就附上FlyBehavior接口和兩個實現類,爲了方便我就放在一塊兒了。學習

package behaviour; public interface FlyBehavior { void fly(); } package behaviour; public class FlyWithWings implements FlyBehavior{ @Override public void fly() { System.out.println("flywithwings"); } } package behaviour; public class FlyNoWay implements FlyBehavior { @Override public void fly() { System.out.println("I can't fly"); } }

接下來咱們就能夠測試這隻「馴化野鴨」的飛行行爲了。測試

測試當中呢,首先先飛行了一下,固然會展現「馴化野鴨」的默認飛行行爲,即「flywithwings」,隨後小鴨子不當心受傷了它暫時不能飛行了,咱們給它動態地從新設置了飛行行爲,最後傷好了,天然又能夠飛行了,而後只須要再從新設置就行了~this

package test; import behaviour.FlyNoWay; import behaviour.FlyWithWings; import object.Duck; import object.concreteobject.MallardDuck; public class Test { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performFly(); System.out.println("------------------------------"); System.out.println("我不當心受傷了,這段時間我不能飛行了。。。"); System.out.println("------------------------------"); mallard.setFlyBehavior(new FlyNoWay()); mallard.performFly(); System.out.println("------------------------------"); System.out.println("我有恢復健康了~"); System.out.println("------------------------------"); mallard.setFlyBehavior(new FlyWithWings()); mallard.performFly(); } }

看,說的沒錯吧。。。。

 

這基本就是我對策略模式的學習總結吧,這個案例也是《Head First設計模式》中的,鴨子(各類鴨子), 各類行爲(行爲1[具體的行爲1,具體的行爲2.......],行爲2[具體的行爲1,具體的行爲2.......]        .......),鴨子有不少種類,有的特殊的鴨子確定有特殊行爲,而行爲可能一時也很差總結,誰知道哪天又會橫空出世一種行爲呢? 鴨子能夠經過策略模式,動態地綁定行爲,而新增行爲,只須要再寫個接口,隨後再Duck類中加上對應的類型的變量就行了。(我仍是再寫一下吧,看看本身是否是真的理解了。。)

 

舉例

原本想繼續擴展鴨子,可是看到書上有另外一案例。。

接下來就是粘貼代碼了,粗略的寫了一下,大概情節就是,角色: 有公主和騎士...,有兩種行爲,使用武器,跳舞,默認公主不會跳舞,和用匕首刺殺,而騎士能夠用寶劍刺殺,沒有跳舞行爲。隨後公主學了跳舞,變有了快樂地跳起了舞~

兩種行爲:

package behaviour; /** * 跳舞 * * @author DeepSleeping * */
public interface DanceBehavior { void dance(); } package behaviour; /** * 可使用武器 * @author DeepSleeping * */
public interface WeaponBehavior { void useWeapon(); }

 

 兩種行爲對應的具體實現(表現):

package behaviour; /** * 快樂地跳舞 * * @author DeepSleeping * */
public class DanceHappy implements DanceBehavior { @Override public void dance() { System.out.println("快樂地跳舞!"); } } package behaviour; /** * 不可能跳舞 * * @author DeepSleeping * */
public class DanceNoWay implements DanceBehavior { @Override public void dance() { System.out.println("我怎麼可能會跳舞!"); } } package behaviour; /** * 使用匕首 * * @author DeepSleeping * */
public class KnifeBehavior implements WeaponBehavior { @Override public void useWeapon() { System.out.println("-使用匕首刺殺-"); } } package behaviour; /** * 使用寶劍 * * @author DeepSleeping * */
public class SwordBehavior implements WeaponBehavior { @Override public void useWeapon() { System.out.println("-使用寶劍刺殺-"); } }

角色,以及角色下的 公主、騎士

package object; import behaviour.DanceBehavior; import behaviour.WeaponBehavior; /** * 角色 * * @author DeepSleeping * */
public abstract class Character { WeaponBehavior wb; DanceBehavior db; public void setDb(DanceBehavior db) { this.db = db; } public void setWb(WeaponBehavior wb) { this.wb = wb; } /** *戰鬥 */
    public void fight() { wb.useWeapon(); } /** * 跳舞 */
    public void dance() { db.dance(); } } package object; import behaviour.DanceNoWay; import behaviour.SwordBehavior; /** * 騎士 * * @author DeepSleeping * */
public class Knight extends Character { public Knight() { // 默認騎士是用寶劍的
        wb = new SwordBehavior(); } } package object; import behaviour.DanceNoWay; import behaviour.KnifeBehavior; /** * 公主 * @author DeepSleeping * */
public class Queen extends Character{ public Queen(){ //默認公主是用匕首的
        wb = new KnifeBehavior(); //默認公主不會跳舞
        db = new DanceNoWay(); } }

開始測試~

package test; import behaviour.DanceHappy; import behaviour.SwordBehavior; import object.Character; import object.Knight; import object.Queen; public class Test { public static void main(String[] args) { Character knight = new Knight(); Character queen = new Queen(); // 騎士去刺殺
 knight.fight(); // 公主去刺殺
 queen.fight(); // 公主換成用寶劍刺殺
        queen.setWb(new SwordBehavior()); queen.fight(); System.out.println("--------------------"); queen.dance(); // 公主學會了跳舞
        queen.setDb(new DanceHappy()); queen.dance(); } }

 

 

 總結

           總結下幾個不錯的設計原則:

      1.找出應用中可能須要變化之處,把它們獨立出來,不要和那些不須要變化的代碼混在一塊兒。

                     2.針對接口編程,而不是針對實現編程。

      3.多用組合,少用繼承

好了 ,策略模式就認識到這了,經過學習,我也算是對策略模式有了初步的認識吧,中間寫着寫着感受好像裝飾者模式啊,哈哈,又有點蒙了,繼續學習吧。。。

 

參考材料:《Head First設計模式》

原文出處:https://www.cnblogs.com/deepSleeping/p/10738020.html

相關文章
相關標籤/搜索