PHP設計模式之策略模式


介紹
策略模式:定義了算法族,分別 封裝起來,讓它們之間可以 互相替換,此模式讓算法的變化 獨立於使用算法的客戶。
 
封裝:把行為用接口封裝起來,我們可以把那些經常變化的部分,從當前的類中單獨取出來,用接口進行單獨的封裝。
互相替換:我們封裝好了接口,通過指定不同的接口實現類進行算法的變化。
 
思維導圖

php策略模式-鴨子游戲

我來解釋下這個思維導圖的過程:
1.Joe做了一套相當成功的模擬鴨子的游戲。設計了一個超類Duck,然后讓各種鴨子繼承這個類。
 
2.后來客戶提出要讓鴨子有飛的能力。所以Joe就在超類中加了個fly()方法,這樣下面的子類都有飛行的行為。
   問題來了:1>原來Duck的子類中竟然有橡皮鴨,橡皮鴨是不會飛的。——Joe用重載的方式,把橡皮鴨的fly()方法設置為空.
                     2>覆蓋fly(),我們看到了橡皮鴨的fly()里,沒有任何代碼,如果以后我們再添加別的不會飛的鴨子,那我么還要這么處理嗎?——那么 代碼重復了!
 
3.上面2的方式我們知道是有問題的,所以Joe想到把Duck做成接口,這樣每個子類必須實現Duck里的方法。這樣就保證每個鴨子都能根據自己的需要添加行為。
     問題來了:產品經常處於更新中,規格也在不斷的變化。導致每當有新鴨子的時候,Joe就要被迫檢查一遍子類是否覆蓋了fly()方法。——當你修改某個行為的時候,你必須得往下追蹤並在每一個定義此行為的類中修改它。
 
4.綜合以上問題,Joe想到了把那些變化的部分從不變化的位置中抽出來。比如,我們對fly()行為,做了單獨的接口FlyBehavior。如果鴨子想要飛行功能的時候,我們就讓鴨子實現FlyBehavior.
 
5.深造:我們想讓鴨子有不同的飛行功能,讓它在運行時候做不同的飛行動作。讓鴨子類實現接口,只能讓鴨子有一種行為。
所以Joe,想到用組合的防止,當鴨子需要其他飛行功能要求的時候,我們可以用setBehavior()方式,指定性的飛行方式。
 
代碼
<?php
interface FlyBehavior{
    public function fly();
}

class FlyWithWings implements FlyBehavior{
    public function fly(){
        echo "Fly With Wings \n";
    }
}

class FlyWithNo implements FlyBehavior{
    public function fly(){
        echo "Fly With No Wings \n";
    }
}
class Duck{
    private $_flyBehavior;
    public function performFly(){
        $this->_flyBehavior->fly();
    }

    public function setFlyBehavior(FlyBehavior $behavior){
        $this->_flyBehavior = $behavior;
    }
}

class RubberDuck extends Duck{
}
// Test Case
$duck = new RubberDuck();

/*  想讓鴨子用翅膀飛行 */
$duck->setFlyBehavior(new FlyWithWings());
$duck->performFly();            

/*  想讓鴨子不用翅膀飛行 */
$duck->setFlyBehavior(new FlyWithNo());
$duck->performFly();

 

總結
總的來說,我們在開發中的設計原則如下:
1.找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起;
2.針對接口編程,不針對實現編程;
3.多用組合,少用繼承;
 
參考文獻: 《head first 設計模式》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM