聲明:本系列部落格參考資料《大話設計模式》,作者程傑。
策略模式定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化,即封裝變化的演算法。
適用情境:
1、 多個類只區別在表現行為不同,可以使用Strategy模式,在運行時動態選擇具體要執行的行為。
2、 需要在不同情況下使用不同的策略(演算法),或者策略還可能在未來用其它方式來實現。
3、 對客戶隱藏具體策略(演算法)的實現細節,彼此完全獨立。
4、用戶端必須知道所有的策略類,並自行決定使用哪一個策略類,策略模式只適用於用戶端知道所有的演算法或行為的情況。
5、 策略模式造成很多的策略類,每個具體策略類都會產生一個新類。
有時候可以通過把依賴於環境的狀態儲存到用戶端裡面,可以使用享元模式來減少對象的數量。
UML類圖:
角色分析:
抽象策略角色(RotateItem):策略類,通常由一個介面或者抽象類別實現。
具體策略角色(ItemX):封裝了相關的演算法和行為。
環境角色(ItemContext):持有一個策略類的引用,最終給用戶端調用。
具體代碼實現:
<?php/** * Created by PhpStorm. * User: Jiang * Date: 2015/5/16 * Time: 21:46 *//**抽象策略角色 * Interface RotateItem */interface RotateItem{ function inertiaRotate(); function unInertisRotate();}/**具體策略角色——X產品 * Class XItem */class XItem implements RotateItem{ function inertiaRotate() { echo "我是X產品,我慣性旋轉了。<br/>"; } function unInertisRotate() { echo "我是X產品,我非慣性旋轉了。<br/>"; }}/**具體策略角色——Y產品 * Class YItem */class YItem implements RotateItem{ function inertiaRotate() { echo "我是Y產品,我<span style='color: #ff0000;'>不能</span>慣性旋轉。<br/>"; } function unInertisRotate() { echo "我是Y產品,我非慣性旋轉了。<br/>"; }}/**具體策略角色——XY產品 * Class XYItem */class XYItem implements RotateItem{ function inertiaRotate() { echo "我是XY產品,我慣性旋轉。<br/>"; } function unInertisRotate() { echo "我是XY產品,我非慣性旋轉了。<br/>"; }}class contextStrategy{ private $item; function getItem($item_name) { try { $class=new ReflectionClass($item_name); $this->item=$class->newInstance(); } catch(ReflectionException $e) { $this->item=""; } } function inertiaRotate() { $this->item->inertiaRotate(); } function unInertisRotate() { $this->item->unInertisRotate(); }}
用戶端調用代碼:
<?php/** * Created by PhpStorm. * User: Jiang * Date: 2015/5/16 * Time: 21:46 */header("Content-Type:text/html;charset=utf-8");require_once "./Strategy/Strategy.php";$strategy=new contextStrategy();echo "<span style='color: #ff0000;'>X產品</span><hr/>";$strategy->getItem('XItem');$strategy->inertiaRotate();$strategy->unInertisRotate();echo "<span style='color: #ff0000;'>Y產品</span><hr/>";$strategy->getItem('YItem');$strategy->inertiaRotate();$strategy->unInertisRotate();echo "<span style='color: #ff0000;'>XY產品</span><hr/>";$strategy->getItem('XYItem');$strategy->inertiaRotate();$strategy->unInertisRotate();
優點:
1、 策略模式提供了管理相關的演算法族的辦法。
策略類的等級結構定義了一個演算法或行為族。
恰當使用繼承可以把公用的代碼轉移到父類裡面,從而避免重複的代碼。
2、 策略模式提供了可以替換繼承關係的辦法。
繼承可以處理多種演算法或行為。
如果不是用策略模式,那麼使用演算法或行為的環境類就可能會有一些子類,每一個子類提供一個不同的演算法或行為。但是,這樣一來演算法或行為的使用者就和演算法或行為本身混在一起。決定使用哪一種演算法或採取哪一種行為的邏輯就和演算法或行為的邏輯混合在一起,從而不可能再獨立演化。繼承使得動態改變演算法或行為變得不可能。
3、 使用原則模式可以避免使用多重條件轉移語句。
多重轉移語句不易維護,它把採取哪一種演算法或採取哪一種行為的邏輯與演算法或行為的邏輯混合在一起,統統列在一個多重轉移語句裡面,比使用繼承的辦法還要原始和落後。
缺點:
1、用戶端必須知道所有的策略類,並自行決定使用哪一個策略類。
這就意味著用戶端必須理解這些演算法的區別,以便適時選擇恰當的演算法類。換言之,策略模式只適用於用戶端知道所有的演算法或行為的情況。
2、 策略模式造成很多的策略類,每個具體策略類都會產生一個新類。
有時候可以通過把依賴於環境的狀態儲存到用戶端裡面,而將策略類設計成可共用的,這樣策略類執行個體可以被不同用戶端使用。換言之,可以使用享元模式來減少對象的數量。
歡迎關注我的視訊課程,地址如下,謝謝。
PHP物件導向設計模式