設計模式(二):策略者模式

轉載請注明作者和出處http://www.itdecent.cn/p/fceff41be9d1

運行平臺: Windows

php版本: php7.0


策略模式,簡單來說,就是完成不同的的任務,卻用相同的方法來實現(xiàn),我們可能見過用到策略模式的地方就是php框架中,封裝了針對不同數(shù)據庫的方法,可是我們卻都能用同一種方法調用他們,我是這么理解的,如果有什么錯誤的地方歡迎指正。

  • 環(huán)境角色(Context):持有一個Strategy的引用
  • 抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現(xiàn)。此角色給出所有的具體的策略類所需的接口
  • 具體策略(ConcreateStrategy)角色:包裝了相關的算法或行為

常用英文單詞:Strategy,Context
最好把設計模式常用的英文單詞用熟,這樣在你閱讀源代碼的時候有很大的幫助,往往大神寫的代碼注釋很少,但是他們的變量名,方法名都符合規(guī)范,你看到這個單詞就知道是怎么一回事,這比無用的注釋好了很多


//定義一個規(guī)范,抽象策略類
abstract class Strategy{
    //小明上學的方法
    abstract function Way();
}

//騎自行車類
class BikeStrategy extends Strategy{
    public function Way()
    {
        echo "騎自行車上學咯";
    }
}

//小車類
class CarStrategy extends Strategy{
    public function Way()
    {
        echo "開車上學咯";
    }
}

//走路上學類
class WalkStrategy extends Strategy{
    public function Way()
    {
        echo "走路上學咯";
    }
}

class SchoolContext{
    private $strategy;//獲取具體策略
    public function __construct(Strategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
    {
        $this->strategy= $strategy;
    }

    public function useRun(){
        $this->strategy->Way();
    }
}

$school = new SchoolContext(new BikeStrategy());
$school->useRun();//騎自行車上學咯
$school = new SchoolContext(new WalkStrategy());
$school->useRun();//走路上學咯

這里我們把實例化的類作為一個參數(shù)注射(依賴注入,內部方法的實現(xiàn)依賴于外部實例化類)進入到學校類之中,我們使用類 Strategy $strategy 限制類必須為繼承Strategy接口的子類,這樣可以有效防止注入大炮火箭之類亂七八糟的東西,好了,那么我們看看策略模式的一些實際應用場景。

<?php

//分享類抽象接口
abstract class ShareStrategy{
    //分享的標題
    abstract function share_title();

    //分享的作者
    abstract function share_author();

    //分享的文章
    abstract function share_content();
}

//微信分享
class WechatShareStrategy extends ShareStrategy{
    //分享的標題
    public function share_title(){
        //標題
    }

    //分享的作者
    public function share_author(){
        //作者
    }

    //分享的文章
    public function share_content(){
        //文章
    }
}

//qq分享
class QQShareStrategy extends ShareStrategy{
    //分享的標題
    public function share_title(){
        //標題
    }

    //分享的作者
    public function share_author(){
        //作者
    }

    //分享的文章
    public function share_content(){
        //文章
    }
}



class ShareContext{
    private $strategy;//保存對象
    public function __construct(ShareStrategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
    {
        $this->strategy = $strategy;
    }

    public function title(){
        $this->strategy->share_title();
    }
    public function author(){
        $this->strategy->share_author();
    }
    public function content(){
        $this->strategy->share_content();
    }
}

class ShareFactory{
    static public function factory($strategy){
        switch($strategy){
            case 'wechat':
                $object = new WechatShareStrategy();
                break;
            case 'qq':
                $object = new QQShareStrategy();
                break;
        }
        return $object;
    }
}

class Article{
    //分享
    public function Share(){
        $strategy = ShareFactory::factory('wechat');
        $shareContext = new ShareContext($strategy);
        $shareContext->title();//微信分享標題
        $shareContext->author();//微信分享作者
        $shareContext->content();//微信分享內容
    }
}

我們這里結合上一章所學的簡單工廠實現(xiàn)了一個分享的簡單例子,當然,簡單工廠也有局限性,就是我們每次增加一個分享類,就要去工廠里增加方法,破化了類的開放封閉原則,我們可以結合類的反射來修改一下ShareFactory方法;

<?php

//分享類抽象接口
abstract class ShareStrategy{
    //分享的標題
    abstract function share_title();

    //分享的作者
    abstract function share_author();

    //分享的文章
    abstract function share_content();
}

//微信分享
class WechatShareStrategy extends ShareStrategy{
    //分享的標題
    public function share_title(){
        echo 'wechat_title'."\n";
        //標題
    }

    //分享的作者
    public function share_author(){
        echo 'wechat_author'."\n";
        //作者
    }

    //分享的文章
    public function share_content(){
        echo 'wechat_content'."\n";
        //文章
    }
}

//qq分享
class QQShareStrategy extends ShareStrategy{
    //分享的標題
    public function share_title(){
        echo 'qq_title';
        //標題
    }

    //分享的作者
    public function share_author(){
        echo 'qq_author';
        //作者
    }

    //分享的文章
    public function share_content(){
        echo 'qq_content';
        //文章
    }
}



class ShareContext{
    private $strategy;//保存對象
    public function __construct(ShareStrategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
    {
        $this->strategy = $strategy;
    }

    public function title(){
        $this->strategy->share_title();
    }
    public function author(){
        $this->strategy->share_author();
    }
    public function content(){
        $this->strategy->share_content();
    }
}

class ShareFactory{

//返回實例化對象
    static public function factory($strategy){
        //$strategy為類的字符串名稱
        $class = new ReflectionClass($strategy);
        return $class->newInstance();
    }
}

class Article{
    //分享
    static public function Share(){
        $strategy = ShareFactory::factory('WechatShareStrategy');
        $shareContext = new ShareContext($strategy);

        $shareContext->title();//微信分享標題
        $shareContext->author();//微信分享作者
        $shareContext->content();//微信分享內容
    }
}
Article::Share();

輸出結果
輸出結果.png

我們通過傳入類的字符串名稱,來進行動態(tài)的實例化類(在框架里一般還會配合spl_autoload_register()這個自動加載類來加載實現(xiàn)實例化類),關于這類實例化類還需要考慮構造函數(shù)的參數(shù)等等因素,我這里比較簡單的提一下,有需要的可以去百度查找一下更詳細的資料,或者以后在依賴注入這一章節(jié)會配合laravle核心ioc容器來詳細講解。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容