1. 程式人生 > >設計模式之 策略模式

設計模式之 策略模式

算法 nal class 我們 mint images iss factor ()

策略模式屬於對象行為型的設計模式

定義 :封裝了一些列算法,它們之前可以相互替換,此模式使得算法的改變,不會影響到使用它們的客戶端

技術分享

策略模式有以下3個角色組成

抽象策略類 : 所有策略類的父類,為所支持的策略算法聲明了抽象方法

具體策略類 :實現抽象策略類的方法

Context環境類 : 維護一個對Strategy對象的引用

策略模式分離了算法的定義和使用,要做到這樣客戶端要依賴於策略接口,而不是具體的實現所有策略類對象可以互相替換,說明具有共同的特性->行為相同

以下是PHP對上述UML的實現

<?php
/*
 *抽象策略類 
 */
abstract class Stratrgy{
    
abstract function AlgorithmInterface(); } //具體實現類A class ConcreateStratrgyA extends Stratrgy{ public function AlgorithmInterface() { echo ‘算法A‘, PHP_EOL; } } //具體實現類B class ConcreateStratrgyB extends Stratrgy{ public function AlgorithmInterface() { echo ‘算法B‘, PHP_EOL; } }
//具體實現類C class ConcreateStratrgyC extends Stratrgy{ public function AlgorithmInterface() { echo ‘算法C‘, PHP_EOL; } } //上下文環境類 class Context{ private $_strategy; //通過構造方法註入策略對像 public function __construct(Stratrgy $strategy) { $this->_strategy = $strategy; } public
function ContextInterface(){ $this->_strategy->AlgorithmInterface(); } } //客戶端類 class Client{ public static function main(){ $context = new Context(new ConcreateStratrgyA()); $context->ContextInterface(); $context = new Context(new ConcreateStratrgyB()); $context->ContextInterface(); $context = new Context(new ConcreateStratrgyC()); $context->ContextInterface(); } } Client::main();

在實際開發中,我們項目裏很多地方都用到了策略模式,這裏以支付回調為栗子介紹下策略模式在我們項目中的應用。

首先所有的支付回調都是由第三方發起,行為相同,最終都是給用戶發送道具並通知第三方。整個流程可以抽象為3個步驟 :驗證第三方參數 ->發送道具給用戶 ->返回報文給第三方,因此我們的抽象策類裏可以定義3個抽象方法,另外一些公共使用的方法都可以放到抽象

策略類裏,具體策略類只需要繼承就可以復用。策略環境類這裏做了一些改動,加入了簡單工廠模式生成具體的策略對象。每種支付的參數驗證,發具體的道具數,以及報文響應都不相同,具體的支付類需要實現3個抽象方法。

由微信切換成支付寶,需要增加對應的支付寶類,然後回調的時候在工廠方法傳入支付寶參數即可,這樣微信,支支付寶...達到了相互替換的目的,而且具體的支付寶微信類改變不會影響到回調的入口。

抽簡後的代碼如下:

<?php
//抽象策略類
abstract class StrategyNotify{
   //參數檢查
   abstract function checkParam();
   //發送道具
   abstract function sendProp();
   //輸出報文
   abstract function outputMessage();
   //支付回調狀態
   protected $_status = -1;
   //第三方參數
   protected $_params = array();

   protected $_errMsg = array(
       ‘-1‘=>‘系統錯誤‘,
       ‘-2‘=>‘參數驗證錯誤‘,
       ‘-3‘=>‘發送道具失敗‘,
   );
   //通知方法
   public final function notify(){
       if(!$this->checkParam()){
           $this->_status = -2;
       }else if(!$this->sendProp()){
           $this->_status = -3;
       }else{
           $this->_status = 1;
       }
       if($this->_status != 1){
           $this->log();
       }
       $this->outputMessage();
   }
   //寫日誌例子
   protected function log(){
       echo isset($this->_errMsg[$this->_status]) ? $this->_errMsg[$this->_status] : ‘‘;
       echo PHP_EOL;
   }
}

//微信支付
class Weixin extends StrategyNotify{
   public function checkParam() {
       return false;
   }

   public function outputMessage() {
       if($this->_status === 1){
           die(‘OK‘);
       }else{
           die(‘FAIL‘);
       }
   }

   public function sendProp() {
       return false;
   }
}

//支付環境類
class Pay{
    private static $_notify = null;
    //策略工廠
    public static function factory($notify){
        if(class_exists($notify) && self::$_notify == null){
            self::$_notify = new $notify();
        }
        return self::$_notify;
    }
}

Pay::factory(‘Weixin‘)->notify();

總結

優點:

1.當新增策略的時候,只需要增加具體的策略類,達到了開閉原則的目的

2.分離了算法的定義和使用,使得算法可以復用

缺點

1.每增加一個策略就需要增加一個策略類(目前我們的app接近200種支付,意味著有200個子類)

2.無法在客戶端同時使用兩種策略(我們的支付下單,需要從多種支付依照優先級一個個去下單,直到成功為止)

設計模式之 策略模式