設計模式之-策略模式

定義一組算法,將每一個算法都封裝起來,而且使它們之間能夠互換。策略模式使這些算法在客戶端調用它們的時候可以互不影響地變化。(Java的TreeSet集合中,構造方法可傳入具體的比較器對象以實現不一樣的排序算法。就是利用的策略模式)策略模式的用意是針對一組算法,將每個算法封裝到具備共同接口的獨立的類中, 從而使得它們能夠相互替換,使用策略模式能夠把行爲和環境分割開來。java

角色

  • 抽象策略角色:策略類,一般由一個接口或者抽象類實現。
  • 具體策略角色:包裝了相關的算法和行爲。
  • 環境角色:持有一個策略類的引用,最終給客戶端調用的。經過環境角色指定策略。算法

    場景假設

    模 擬 鴨 子 遊 戲 :SimUDuck。遊戲中會出現各類鴨子,一邊游泳戲水,一邊呱
    呱叫。不一樣的鴨子有不一樣的行爲,因此咱們能夠把鴨子會不會飛,怎麼飛的行爲定義爲抽象策略角色,鴨子叫行爲也定義成一種策略,由於叫法不一樣。ide

    分開變與不變

    把會變化的部分取出並封裝起來,以便之後能夠輕易地改動或擴充此部分,而不影響不須要變化的其餘部分。
    咱們先抽象一個Duck類,鴨子有 fly() 和 quack() ,可是會隨着鴨子的不一樣而改變,因此咱們要抽出來,將他們定義爲變的部分涉及成策略,Duck 類持有對應策略的引用,經過組合的方式實現。
    image.pngthis

    設計類圖

    image.png
    最後咱們整合鴨子的行爲,分別將鴨子的飛行與嘎嘎叫的動做 "委託"(delagate)別人處理,而不是定義在Duck類中。
    咱們用兩個類似的方法performFly()和performQuack()取代鴨子類中的fly()與quack()。設計

代碼實現

定義 Duck 抽象類,全部的鴨子都繼承。經過組合代理的模式實現飛行與嘎嘎叫的功能,持有策略類(飛行,呱呱叫)的引用。
提供set方法指定不一樣的策略,而後經過 performFly 與 performQuack 委託對應的策略實現。代理

環境角色

public abstract class Duck {

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    /**
     * 展現鴨子
     */
    public abstract void display();


    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

定義野鴨子:會飛,呱呱叫。code

public class MallardDuck extends Duck {
    @Override
    public void display() {
        System.out.println("我是一隻野鴨子");
    }
}

定義模型鴨子:不會飛也不會叫。orm

public class ModelDuck extends Duck {
    @Override
    public void display() {
        System.out.println("我是一隻模型鴨子");
    }
}

策略抽象角色 FlyBehavior 、QuackBehavior

叫聲抽象策略對象

public interface QuackBehavior {
    void quack();
}

飛行抽象策略blog

public interface FlyBehavior {
    void fly();
}

策略具體角色

實現抽象策略,規定算法邏輯。

  • 不會飛的策略
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("老司機帶帶我,我不會飛");
    }
}
  • 會飛的策略
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我會飛行,一衝雲霄");
    }
}
  • 叫聲策略呱呱叫實現
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("呱呱叫");
    }
}
  • 叫聲策略: 不會叫策略
public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("我不會叫");
    }
}

生成不一樣的鴨子

  • 會叫的野鴨子
public class MallardDuck extends Duck {
    @Override
    public void display() {
        System.out.println("我是一隻野鴨子");
    }
}
  • 不會叫的模型鴨子
public class ModelDuck extends Duck {
    @Override
    public void display() {
        System.out.println("我是一隻模型鴨子");
    }
}

定義顯示屏展現鴨子

public class MiniDuckSimulator {
    public static void main(String[] args) {

        //定義不會叫不會飛的鴨子
        FlyBehavior flyBehavior = new FlyNoWay();
        QuackBehavior quackBehavior = new MuteQuack();
        Duck modelDuck = new ModelDuck();
        //這裏咱們能夠設置不一樣的行爲實現類就會執行不一樣的策略
        modelDuck.setFlyBehavior(flyBehavior);
        modelDuck.setQuackBehavior(quackBehavior);

        modelDuck.display();
        modelDuck.performFly();
        modelDuck.performQuack();
        System.out.println("-------------------");

        // 定義會叫會飛的鴨子
        FlyBehavior flyWithWings = new FlyWithWings();
        QuackBehavior quack = new Quack();
        Duck mallardDuck = new MallardDuck();

        mallardDuck.setFlyBehavior(flyWithWings);
        mallardDuck.setQuackBehavior(quack);

        mallardDuck.display();
        mallardDuck.performFly();
        mallardDuck.performQuack();

    }
}

其實就是將將不一樣的算法抽象,經過上下文切換策略實現不一樣行爲。咱們是否是還可使用策略模式代替不少的if else 判斷執行不一樣的算邏輯?這裏留給讀者去發現使用場景。
關注公衆號 JavaStorm 獲取最新文章,不點個贊麼?
JavaStorm

相關文章
相關標籤/搜索