[淺談設計模式(三)] 讓你一分鐘讀懂設計模式

best輝發表於2019-05-29

碎碎念:

在此分享的是我學習中的一些理解和總結,大家一起學習和共勉,希望對大家有所幫助;在大家看了以後,覺得我理解和總結有不到位或者不對的地方希望大家在留言區指出,我會及時修改,感謝!!!

前言:

這篇文章接續上一篇文章,上一篇主要分享的是單例模式和介面卡模式,如果有沒有看過第二篇文章的朋友,下面有連結(淺談設計模式(二))。該篇主要分享的設計模式是:觀察者模式和策略模式。分享的每個設計模式都會透過 3 個方面(定義、舉例說明、程式碼說明)進行講解和說明。

正文:

觀察者模式

1.定義:
定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新,簡單來說該模式相當於源 - 監聽(Source-Listener)模式(即監聽器)、釋出 - 訂閱(Publish-Subscribe)模式
2.舉例說明:
大家看這個例子的時候,最好結合下面的程式碼說明一起更好理解.
有一個軍營(即RegListener類),我們要想成為士兵(即觀察者),首先需要去軍營裡面註冊成為士兵(即RegListener下的add()方法),註冊成功後我們就成為了真正計程車兵(即listener1),所有計程車兵要聽從將軍的命令進行戰鬥(即所有listener類要實現update()方法),這時敵軍來犯,將軍釋出命令(即我們呼叫notice()方法),所有士兵收到命令後就開始戰鬥(即所有的listener類執行update()方法)。
這樣的舉例不知道大家是否能接受,思考了半天,感覺還是好尬呀!
3.程式碼說明:
A. 註冊觀察者(監聽)的介面

interface Subject {
 public function add(Observer $observer);//增加一個新的觀察者物件
 public function del(Observer $observer);//刪除一個已註冊過的觀察者物件
 public function notice();// 通知所有註冊過的觀察者物件

B. 具體實現註冊觀察者類(監聽事件)

/**
* 具體主題角色(實現觀察者註冊類)
*/
class RegListener implements Subject {
    private $listen;

    public function __construct() {
        $this->listen = array();
    }
    //增加一個新的觀察者物件
    public function add(classname $class_object) {
        if(!in_array($class_object,$this->listen)){
            $this->listen[classname] = $class_object;
        }
    }
   // 刪除一個已註冊過的觀察者物件
    public function del(classname $class_object) {
       if(isset($this->listen[classname])){
           unset($this->listen[classname]);
           return true;
       }
        return TRUE;
    }
    //通知所有註冊過的觀察者物件(觸發觀察者)
    public function notice() {
        //判斷是否有註冊過觀察者
        if (!is_array($this->listen)) {
            return FALSE;
        }
       //觸發所有觀察者
        foreach ($this->listen as $classname=>$class_object) {
            $class_object->update($key,$val);  //觀察者的操作(如:文章瀏覽+1,文章總數+1,積分+1)
        }
        return TRUE;
    }
}

C. 觀察者的介面和操作方法(所有觀察者呼叫介面,統一實現同一個名稱的方法)

//觀察者操作方法介面
interface ListenMethod  
{  
    function update($class_object);  //觀察者方法【統一方法名】  ($class_object類例項化物件)
} 
//觀察者1(文章瀏覽量+1)
class listener1 implements ListenMethod  
{  
    public function update(classnam $class_object)  
    {  
        $class_object-> setCount(1);  //setCount()可以重新定義成文章+1或其他文章瀏覽+1或其他邏輯操作  
    }  
}  
//觀察者2(積分量+10)
class listener2 implements ListenMethod  
{  
    public function update(classnam $class_object)  
    {  
        $class_object-> setIntegral(10);    //setIntegral()也是我們監聽成功後要執行的方法
    }  
}  

D. 觀察者模式的呼叫

class Achieve 
{  
    public  function test()  
    {  
        $Listener = new RegListener();   //例項化觀察者角色介面,用於註冊觀察者
        $Listener->add(new listener1());   //註冊文章瀏覽+1觀察者
        $Listener->add(new listener2());  //註冊積分+1觀察者  
        $Listener->notice();//觸發監聽和觀察者方法:文章瀏覽量加1 積分量加10  
    }  
} 

策略模式

1.定義: 白話理解就是用相同的方法實現不同的功能
2.舉例說明:
常見的排序演算法有快速排序,氣泡排序,歸併排序,選擇排序等,它們實現的方法都是sort(),那麼問題來了,我們怎麼只透過sort()方法就可以呼叫所有的排序演算法呢。這時,我們引入一個類,幫助我們實現。
3.程式碼說明:
A.Strategy (抽象策略介面類)

//抽象策略介面
  abstract class Strategy{
      abstract function sort();  //具體策略類要實現的方法
  }

B.ConcreteStrategy (具體策略類)

class StrategyA extends Strategy
  {
      public function sort()
      {
          echo "這個類是氣泡排序類 <br>";
      }
  }

 class  StrategyB  extends  Strategy 
 {  
     public  function  sort() 
     {  
         echo  "這個類是快速排序類 <br>";  
     } 
}

C.Context 類(如何實現策略類,即我們引入的類)

//實現具體策略類
class Context{ 
    protected $strategy; 
    //建構函式的引數是一個具體策略類的物件
    public function __construct(Strategy $strategy) 
    { 
        $this->strategy = $strategy; 
    } 
    public function request() 
    { 
        $this->strategy->sort();   //實現具體排序類方法
    }
}

D. 實現策略類

//呼叫StrategyA氣泡排序類
$strategyA = new StrategyA();
$context = new Context($strategyA);  
$context->request();    

//呼叫StrategyB快速排序類
$strategyB = new StrategyB();
$context = new Context($strategyB);  
$context->request();  

上一篇分享:【淺談設計模式(二)】部落格:[淺談設計模式(二)] 讓你一分鐘讀懂設計模式

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章