複製鏈接
請複製以下鏈接發送給好友

策略模式

鎖定
策略模式是指有一定行動內容的相對穩定的策略名稱。策略模式在古代中又稱“計策”,簡稱“計”,如《漢書·高帝紀上》:“漢王從其計”。這裏的“計”指的就是計謀、策略。策略模式具有相對穩定的形式,如“避實就虛”、“出奇制勝”等。一定的策略模式,既可應用於戰略決策,也可應用於戰術決策;既可實施於大系統的全局性行動,也可實施於大系統的局部性行動。
中文名
策略模式
外文名
Pattern:Strategy
抽象策略角色
由一個接口或者抽象類實現
具體策略角色
包裝了相關的算法和行為
環境角色
持有一個策略類的引用

策略模式簡介

策略模式作為一種軟件設計模式,指對象有某個行為,但是在不同的場景中,該行為有不同的實現算法。比如每個人都要“交個人所得税”,但是“在美國交個人所得税”和“在中國交個人所得税”就有不同的算税方法。
策略模式:
  • 定義了一組算法(業務規則);
  • 封裝了每個算法;
  • 這族的算法可互換代替(interchangeable)。 [1] 

策略模式組成

—抽象策略角色: 策略類,通常由一個接口或者抽象類實現。
—具體策略角色:包裝了相關的算法和行為。
—環境角色:持有一個策略類的引用,最終給客户端調用。 [2] 
策略模式UML圖 策略模式UML圖

策略模式應用場景

應用場景:
1、 多個類只區別在表現行為不同,可以使用Strategy模式,在運行時動態選擇具體要執行的行為。
2、 需要在不同情況下使用不同的策略(算法),或者策略還可能在未來用其它方式來實現。
3、 對客户隱藏具體策略(算法)的實現細節,彼此完全獨立。 [1] 

策略模式優缺點

策略模式優點

1、 策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行為族。恰當使用繼承可以把公共的代碼轉移到父類裏面,從而避免重複的代碼。
2、 策略模式提供了可以替換繼承關係的辦法。繼承可以處理多種算法或行為。如果不是用策略模式,那麼使用算法或行為的環境類就可能會有一些子類,每一個子類提供一個不同的算法或行為。但是,這樣一來算法或行為的使用者就和算法或行為本身混在一起。決定使用哪一種算法或採取哪一種行為的邏輯就和算法或行為的邏輯混合在一起,從而不可能再獨立演化。繼承使得動態改變算法或行為變得不可能。
3、 使用策略模式可以避免使用多重條件轉移語句。多重轉移語句不易維護,它把採取哪一種算法或採取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統統列在一個多重轉移語句裏面,比使用繼承的辦法還要原始和落後。

策略模式缺點

1、客户端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客户端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客户端知道所有的算法或行為的情況。
2、 策略模式造成很多的策略類,每個具體策略類都會產生一個新類。有時候可以通過把依賴於環境的狀態保存到客户端裏面,而將策略類設計成可共享的,這樣策略類實例可以被不同客户端使用。換言之,可以使用享元模式來減少對象的數量。 [2] 

策略模式實現:

出行旅遊:
圖1 UML類圖 圖1 UML類圖

策略模式代碼實現:

<?php

/**
*策略模式
*定義一系列的算法,把每一個算法封裝起來,並且使它們可相互替換。
*本模式使得算法可獨立於使用它的客户變化
*/

/**
*出行旅遊
*/
interface TravelStrategy{
    public function travelAlgorithm();
}

/**
*具體策略類(ConcreteStrategy)
*1:乘坐飛機
*/
class AirPlanelStrategy implements TravelStrategy{
    public function travelAlgorithm(){
        echo"travelbyAirPlain","<BR>\r\n";
    }
}

/**
*具體策略類(ConcreteStrategy)
*2:乘坐火車
*/
class TrainStrategy implements TravelStrategy{
    public function travelAlgorithm(){
        echo"travelbyTrain","<BR>\r\n";
    }
}
/**
*具體策略類(ConcreteStrategy)
*3:騎自行車
*/
class BicycleStrategy implements TravelStrategy{
    public function travelAlgorithm(){
        echo"travelbyBicycle","<BR>\r\n";
    }
}

/**
*
*環境類(Context):
*用一個ConcreteStrategy對象來配置。
*維護一個對Strategy對象的引用。可定義一個接口來讓Strategy訪問它的數據。
*算法解決類,以提供客户選擇使用何種解決方案:
*/
class PersonContext{
    private$_strategy = null;
    public function __construct(TravelStrategy$travel){
        $this->_strategy=$travel;
    }
    /**
    *旅行
    */
    public functionset TravelStrategy(TravelStrategy$travel){
        $this->_strategy=$travel;
    }
    /**
    *旅行
    */
    public function travel(){
        return$this->_strategy->travelAlgorithm();
    }

}
//乘坐火車旅行
$person=newPersonContext(newTrainStrategy());
$person->travel();

//改騎自行車
$person->setTravelStrategy(newBicycleStrategy());
$person->travel();
}
參考資料
  • 1.    "The Strategy design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-12.
  • 2.    "The Strategy design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.