PHP行為型設計模式(四)

fangle發表於2017-05-25

續上一篇:PHP行為型設計模式(三),本文介紹第四類行為型設計模式。

通過中間類

  • 訪問者模式(Visitor Pattern)
  • 中介者模式 ( Mediator Pattern)
  • 直譯器模式(Interpreter Pattern)

PHP設計模式(二十)—訪問者模式(Visitor Pattern)

訪問者模式(Visitor Pattern) : 表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變各元素類的前提下定義作用於這些元素的新操作。

(一)為什麼需要訪問者模式

訪問者模式能夠在不更改物件的情況下向該物件新增新的功能性

(二)訪問者模式 UML圖

PHP行為型設計模式(四)
Visitor Pattern

訪問者模式UML圖通常是比較複雜,如果對於只有一個元素和一種訪問者,我們其實也可以不用抽象元素和抽象訪問者,不要objectStruct
下圖給出《PHP設計模式》中的訪問者模式UML圖。

PHP行為型設計模式(四)
Visitor Pattern

(三)簡單例項

由於訪問者模式的複雜,可能一開始大家看了好久也不知其所然。我也是看了好久都不知道訪問者模式的意思。所以這裡我只用《PHP設計模式》一書中的UML圖,實現如何在不更改物件的情況下向該物件新增新的功能性。

<?php
//具體元素
class Superman{
    public $name;
    public function doSomething(){
        echo '我是超人,我會飛'.PHP_EOL;
    }
    public function accept(Visitor $visitor){
        $visitor->doSomething($this);
    }
}
//具體訪問者
class Visitor{
    public function doSomething($object){
        echo '我可以返老還童到'.$object->age = 18;
    }
}
//例項化具體物件
$man = new Superman;
//使用自己的能力
$man->doSomething();
//通過新增訪問者,把訪問者能能力擴充套件成自己的
$man->accept(new Visitor);複製程式碼

我們可以看到,通過呼叫accept方法接收一個訪問者,具體物件可以把訪問者的doSomething能力也擴充套件為自己能力。當然如果你需要多個擴充套件能力,你可以有多個訪問者。而accept方法呼叫訪問者的dosomething方法時,傳入$this是為了能使用Superman的屬性和方法,使其感覺擴充套件完就是Superman的真正一部分。


PHP設計模式(二十一)—中介者模式(Mediator Pattern)

中介者模式(Mediator Pattern): 用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。中介者模式又稱為調停者模式,它是一種物件行為型模式。

(一)為什麼需要中介者模式

1,中介者模式可以使物件之間的關係數量急劇減少。

2,中轉作用(結構性):通過中介者提供的中轉作用,各個同事物件就不再需要顯式引用其他同事,當需要和其他同事進行通訊時,通過中介者即可。該中轉作用屬於中介者在結構上的支援。

3,協調作用(行為性):中介者可以更進一步的對同事之間的關係進行封裝,同事可以一致地和中介者進行互動,而不需要指明中介者需要具體怎麼做,中介者根據封裝在自身內部的協調邏輯,對同事的請求進行進一步處理,將同事成員之間的關係行為進行分離和封裝。該協調作用屬於中介者在行為上的支援。

(二)中介者模式 UML圖

PHP行為型設計模式(四)
Mediator Pattern

(三)簡單例項

中介者模式的思想在現實生活中也很常見,比如說交換機。沒有交換機存在的時代,每個電話之間都需要電話線連線才能進行通話。如果一個臺電話要和其它100臺電話通話,那麼它就必須要有100條電話線與其它100個電話連線。

後來為了解決這種麻煩,交換機出現了。每個電話只需連入交換機,通話時。只需構建一條電話-交換機-電話的鏈路,就可以進行通話。所以現在我們的電話理論上可以同世界上任何一臺電話通話,但是隻需一條電話線。當然現在用電話的人少了,但是手機呀,計算機網路的實現也是在傳統通訊網的設計上進行演進的。

其實交換機對應的就是中介者模式的中介者,而電話機就是中介者中的同事。下面,就讓我們用程式碼來實現這個思想。

<?php
//抽象同事類 --------電話機
abstract class Colleague{
    protected $mediator;    //用於存放中介者
    abstract public function sendMsg($num,$msg);
    abstract public function receiveMsg($msg);
    //設定中介者
    final public function setMediator(Mediator $mediator){
      $this->mediator = $mediator;
    }
}
//具體同事類 ---------座機
class Phone extends Colleague
{
    public function sendMsg($num,$msg)
    {
      echo __class__.'--傳送聲音:'.$msg.PHP_EOL;
      $this->mediator->opreation($num,$msg);
    }

    public function receiveMsg($msg)
    {
      echo __class__.'--接收聲音:'.$msg.PHP_EOL;
    }
}
//具體同事類----------手機
class Telephone extends Colleague
{
    public function sendMsg($num,$msg)
    {
        echo __class__.'--傳送聲音:'.$msg.PHP_EOL;
        $this->mediator->opreation($num,$msg);
    }
    //手機接收資訊前 會智慧響鈴
    public function receiveMsg($msg)
    {   
        echo '響鈴-------'.PHP_EOL;
        echo __class__.'--接收聲音:'.$msg.PHP_EOL;
    }
}
//抽象中介者類
abstract class Mediator{
  abstract public function opreation($id,$message);
  abstract public function register($id,Colleague $colleague);
}
//具體中介者類------交換機
class switches extends Mediator
{
    protected  $colleagues = array();
    //交換機業務處理
    public function opreation($num,$message)
    {
        if (!array_key_exists($num,$this->colleagues)) {
            echo __class__.'--交換機內沒有此號碼資訊,無法通話'.PHP_EOL;
        }else{
            $this->colleagues[$num]->receiveMsg($message);
        }
    }
    //註冊號碼
    public function register($num,Colleague $colleague)
    {
      if (!in_array($colleague, $this->colleagues)) {
          $this->colleagues[$num] = $colleague;
      }
      $colleague->setMediator($this);
    }
}
//例項化固話
$phone = new Phone;
//例項化手機
$telephone = new Telephone;
//例項化交換機
$switches = new Switches;
//註冊號碼  ---放號
$switches->register(6686668,$phone);
$switches->register(18813290000,$telephone);
//通話
$phone->sendMsg(18813290000,'hello world');
$telephone->sendMsg(6686668,'請說普通話');
$telephone->sendMsg(6686660,'你好');複製程式碼

PHP設計模式(二十二)—中介者模式(Mediator Pattern)

直譯器模式(Interpreter Pattern): 提供了評估語言的語法或表示式的方式,它屬於行為型模式。這種模式實現了一個表示式介面,該介面解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等
(一)為什麼需要直譯器模式

可以將一個需要解釋執行的語言中的句子表示為一個抽象語法樹

(二)直譯器模式UML圖

PHP行為型設計模式(四)
Interpreter Pattern

(三)簡單例項

直譯器模式是開發中最少使用的,因為我們親自編寫語法解析的時候總是非常非常少。而且我能想到的直譯器模式例子,幾乎都是程式碼繁多到我自己怕,關鍵是我自己也對這模式有點懵。所以這裡我只給出直譯器模式的UML圖通用程式碼。

<?php
//抽象表示式 
abstract class Expression{
    //任何表示式子類都應該有一種解析任務
    abstract public function interpreter($context);
}
//抽象表示式是生成語法集合(語法樹)的關鍵,每個語法集合完成指定語法解析任務
//抽象表示式通過遞迴呼叫的方法,最終由最小語法單元進行解析完成

//終結符表示式    通常指運算變數
class TerminalExpression extends Expression{
    //終結符表示式通常只有一個
    public function interpreter($context){
        return null; //視具體業務實現
    }
}
//非終結符表示式   通常指運算的符號
class NonterminalExpression extends Expression{
    public function interpreter($context){
        return null;
    }
}複製程式碼

上一篇::PHP行為型設計模式(三)

感謝閱讀,由於筆者也是初學設計模式,能力有限,文章不可避免地有失偏頗
後續更新 PHP設計模式(雜項)介紹,歡迎大家評論指正


我最近的學習總結:


PHP行為型設計模式(四)
歡迎大家關注我的微信公眾號 火風鼎

相關文章