首頁  >  文章  >  後端開發  >  PHP物件導向進階設計模式:觀察者模式使用實例

PHP物件導向進階設計模式:觀察者模式使用實例

巴扎黑
巴扎黑原創
2017-05-23 13:45:561586瀏覽

什麼是觀察者模式?

觀察者設計模式能夠更便利地建立查看目標對象狀態的對象,並且提供與核心對象非耦合的指定功能性。

該模式非常簡單:一個物件透過添加一個方法(該方法允許另一個對象,即觀察者 註冊自己)使本身變得可觀察。當可觀察的物件變更時,它會將訊息傳送到已註冊的觀察者。這些觀察者使用該資訊執行的操作與可觀察的物件無關。結果是對象可以相互對話,而不必了解原因。


UML

#此圖詳細說明了一個使用觀察者設計模式的類別設計:

PHP物件導向進階設計模式:觀察者模式使用實例

下面是對上圖的說明:

1.MyObject是可觀察對象,它包含一個名為observers的觀察者保護陣列。公共方法addObserver()接受一個觀察者的實例並將其儲存在觀察者陣列內。

2.doSomething()公共方法會被調用,這個方法對MyObject應用狀態變化。隨後,notify()公共方法會被調用,這個方法可遍歷循環觀察者數組。

3.MyObjectObserver有一個名為change()的公用方法,該方法接受MyObject的一個實例。這個特定的觀察者接下來會對MyObject的內容執行某些操作。當在觀察者陣列中找到特定的觀察者時,MyObject的notify()方法會直接呼叫change()方法。

使用實例:

<?php  
interface Observable{  
    function attach( Observer $observer );  
    function detach( Observer $observer );  
    function notify();  
}  
  
  
class login implements Observable{  
    const LOGIN_USER_UNKNOW = 1;  
    const LOGIN_WRONG_PASS = 2;  
    const LOGIN_ACCESS = 3;  
    private $status = array();  
    private $observers = array();  
  
    public function setStatus( $status, $user, $ip ) {  
        $this->status = array( $status, $user, $ip );  
    }  
    public function getStatus() {  
        return $this->status;  
    }  
    public function handleLogin( $user, $pass, $ip ) {  
        switch ( mt_rand( 1, 3 ) ) {  
        case 1:  
            $this->setStatus( self::LOGIN_USER_UNKNOW, $user, $ip );  
            $ret = false;  
            break;  
        case 2:  
            $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip );  
            $ret = false;  
            break;  
        case 3:  
            $this->setStatus( self::LOGIN_ACCESS, $user, $ip );  
            $ret = true;  
            break;  
        }  
        $this->notify();  
        return $ret;  
    }  
  
  
    public function attach( Observer $observer ) {  
        $this->observers[] = $observer;  
    }  
  
    public function detach( Observer $observer ) {  
        $newObservers = array();  
        foreach ( $this->observers as $obs ) {  
            if ( $obs !== $observer )  
                $newObservers[] = $obs;  
        }  
        $this->observers = $newObservers;  
    }  
  
    public function notify() {  
        foreach ( $this->observers as $obs ) {  
            $obs->update( $this );  
        }  
    }  
}  
  
interface Observer{  
    function update( Observable $observable );  
}  
  
class SecurityMonitor implements Observer{  
    function update( Observable $observable ) {  
        $status = $observable->getStatus();  
        if($status[0] == Login::LOGIN_WRONG_PASS){  
            echo __CLASS__.":".$status[1]."于".$status[2]."登录失败";  
        }  
    }  
}  
  
$login = new Login();  
$login->attach(new SecurityMonitor());  
$login->handleLogin(&#39;XXX&#39;,&#39;XXX&#39;,&#39;127.0.0.1&#39;);  
?>  
出错时的运行结果:  
SecurityMonitor:XXX于127.0.0.1登录失败[Finished in 0.1s]

程式碼中可以看到login物件主動加入SecurityMonitor物件觀察。這樣要呼叫Login::getStatus(),SecurityMonitor類別就必須了解更多資訊。雖然呼叫發生於一個ObServable物件上,但無法保證物件也是一個Login物件。為解決這個問題,有一個方法:斷斷續續保持ObServable介面的通用性,由ObServer類別負責保證它們的主體是正確的類型。它們甚至能將自己添加到主體上。

以上是PHP物件導向進階設計模式:觀察者模式使用實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn