【讀書筆記-重構與模式】 觀察者模式–將客戶元素從主體中分離

來源:互聯網
上載者:User

觀察者模式的核心是把客戶元素(觀察者)從一個中心類(主體)中分離出來。當主體知道時間發生時,觀察者需要被通知到。同時,不需要主體和觀察者之間進行寫入程式碼。

《設計模式》中對Observer模式的意圖的描述是:“定義對象間的一對多的依賴關係,當一個對象的狀態發生變化時,所有依賴於它的對象都能到得到通知並自動更新”

Observer模式用到的幾條物件導向的原則也值得關註:

1.對象自我負責:Observer對象有多種,但是都從Subject對象手機所需資訊,並自己完成相應的操作。

2.抽象類別(介面):Observer類(介面)表示了“需要通知的對象”這一概念,它為目標提供了一個通知observer的公用介面。

3.多態封裝:Subject並不知道與那種觀察者通訊。實際上,observer類封裝了各種特定的observer.這以為這如果我在未來有新的observer,不需要更改subject類。

《深入php物件導向模式與實踐》給給出的例子:

假設我們有一個login類處理使用者的登陸資訊,當使用者登入時,根據使用者的登入狀態,做相應的動作。如果不對login對象和相應的動作做硬式編碼話。observer模式是一個極佳的選擇。

Observable 介面(主體):

interface Observable{    function attach(Observer $observer);    function detach(Observer $observer);    function notify();}

具體的Login(登入主體):

class login implements Observable{    const LOGIN_ACCESS = 1;    const LOGIN_WRONG_PASS = 2;    const LOGIN_USER_UNKNOWN = 3;    private $status = array();    private $observers;    public function __construct(){        $this->observers = array();    }    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;    }    private function setStatus($status,$user,$ip){        $this->status = array($status,$user,$ip);    }    public function getStatus(){        return $this->status;    }    public function notify(){        foreach($this->observers as $obs){            $obs->update($this);        }    }    public function handlerLogin( $user,$pass,$ip){        switch(rand(1,3)){            case 1:                $this->setStatus(Self::LOGIN_ACCESS,$user,$ip);                $ret = true;break;            case 2:                $this->setStatus(Self::LOGIN_WRONG_PASS,$user,$ip);                $ret = false;break;            case 3:                $this->setStatus(Self::LOGIN_USER_UNKNOWN,$user,$ip);                $ret = true;break;        }    }}

觀察者介面:

interface Observer{    function update(Observable $observable);}

抽象的login觀察者類:

abstract class LoginObserver implements Observer{    private $login;    public  function __construct(Login $login){        $this->login = $login;        $login->attach($this);    }    public function update(Observable $observable){        if($observable == $this->login){            $this->doUpdate($observable);        }    }    abstract private function doUpdate( Login $login );}

具體的觀察者類:

//觀察者1:登入失敗時候發送郵件class SecurityMonitor extends LoginObserver{    private function doUpdate( Login $login ){        $status = $login->getStatus();        if($status[0] == Login::LOGIN_WRONG_PASS){            print __CLASS__."\tsending mail to sysadmin";        }    }}//觀察者2:記錄登入日誌class GeneralLogger extends LoginObserver{    private function doUpdate(Login $login){        $status = $login->getStatus();        //LOG        print __CLASS__."[status]:{$status}\tadd login data to log";    }}//觀察者3:設定cookieclass PartnerShipTool extends LoginObserver{    private function doUpdate(Login $login){        $status = $login->getStatus();        //COOKIE        print __CLASS__."[Cookie]:{$status}\t set cookie to a list";    }}

各個類之間的類圖關係如所示:

PHP內建的SPL擴充提供了對觀察者模式的原生態支援。其中的觀察者有三個元素組成,SplObserver,SplSubject,SplStorage.其中SplObserver,SplSubject都是介面。SplStorage是個工具類,用於更好滴儲存對象和刪除對象。

有SPL的支援,實現觀察者模式更加方便一些了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.