PHP設(shè)計(jì)模式-觀察者模式

觀察者模式

問題引入

一個(gè)系統(tǒng)在用戶登錄的時(shí)候,經(jīng)常要記錄一些東西:session、登錄次數(shù)、統(tǒng)計(jì)在線時(shí)長(zhǎng)等;如果這么多的操作按照面向過程的方法編寫,使一個(gè)對(duì)象變得復(fù)雜,它要操作這么多的事情,這樣也違反單一功能原則。

如果這些操作以插件形式加載或移除,那么登錄只完成它的單一功能操作。

  • 這樣就可以使用觀察者模式,后期再增加相關(guān)功能模塊,不需要太多工作就可以加載同步;也不用修改登錄的功能(符合開閉原則);
  • 缺點(diǎn)就是因?yàn)楦鱾€(gè)插件模塊分散,后面功能可能重疊之前的功能,導(dǎo)致數(shù)據(jù)錯(cuò)誤,所以在使用時(shí)要盡量注釋或者整理好文檔

使用場(chǎng)景

  • 當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面。
  • 當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象,而不知道具體有多少個(gè)對(duì)象待改變。
  • 當(dāng)一個(gè)對(duì)象必須通知其它對(duì)象,而它又不能假定其它對(duì)象是誰。換句話說,你不希望這些對(duì)象是緊密耦合的

如何使用

php已經(jīng)提供了主題接口類和觀察者接口類,還有一個(gè)SplObjectStorage數(shù)據(jù)結(jié)構(gòu)對(duì)象容器——實(shí)現(xiàn)了Countable,Iterator,Serializable,ArrayAccess四個(gè)接口??蓪?shí)現(xiàn)統(tǒng)計(jì)、迭代、序列化、數(shù)組式訪問等功能。

  • 主題類(被觀察者)
namespace Observer;


use SplObjectStorage;
use SplObserver;
use SplSubject;

class User implements SplSubject
{
    /**
     * @var SplObjectStorage
     */
    private $observers;

    public function __construct()
    {
        $this->observers = new SplObjectStorage();
    }

    /**
     * Attach an SplObserver
     * @link http://php.net/manual/en/splsubject.attach.php
     * @param SplObserver $observer <p>
     * The <b>SplObserver</b> to attach.
     * </p>
     * @return void
     * @since 5.1.0
     */
    public function attach(SplObserver $observer)
    {
        $this->observers->attach($observer);
    }

    /**
     * Detach an observer
     * @link http://php.net/manual/en/splsubject.detach.php
     * @param SplObserver $observer <p>
     * The <b>SplObserver</b> to detach.
     * </p>
     * @return void
     * @since 5.1.0
     */
    public function detach(SplObserver $observer)
    {
        $this->observers->detach($observer);
    }

    /**
     * Notify an observer
     * @link http://php.net/manual/en/splsubject.notify.php
     * @return void
     * @since 5.1.0
     */
    public function notify()
    {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
}
  • 觀察者1
namespace Observer;


use SplObserver;
use SplSubject;

class UserObserver implements SplObserver
{

    /**
     * Receive update from subject
     * @link http://php.net/manual/en/splobserver.update.php
     * @param SplSubject $subject <p>
     * The <b>SplSubject</b> notifying the observer of an update.
     * </p>
     * @return string
     * @since 5.1.0
     */
    public function update(SplSubject $subject)
    {
        echo '我是觀察者1:獲取用戶信息' . '<br>';
    }
}
  • 觀察者2
namespace Observer;


use SplSubject;

class OntimeObserver implements \SplObserver
{

    /**
     * Receive update from subject
     * @link http://php.net/manual/en/splobserver.update.php
     * @param SplSubject $subject <p>
     * The <b>SplSubject</b> notifying the observer of an update.
     * </p>
     * @return string
     * @since 5.1.0
     */
    public function update(SplSubject $subject)
    {
        echo '我是觀察者2:記錄用戶在線時(shí)間' .'<br>';
    }
}
  • 實(shí)施調(diào)用

use Observer\OntimeObserver;
use Observer\User;
use Observer\UserObserver;

spl_autoload_register(function($class_name) {
    $class_file = realpath(dirname(__FILE__)."/../") .'/' . str_replace('\\','/', $class_name) . '.php';
    if (file_exists($class_file)) {
        include $class_file;
    } else {
        echo "加載文件失敗";
    }
});

//實(shí)例化主題類
$user = new User();

//添加觀察者
$user->attach(new UserObserver());
$user->attach(new OntimeObserver());

//通知觀察者
$user->notify();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 我是一名90后的未婚媽咪,我和他一開始由于年齡不夠,未能領(lǐng)結(jié)婚證。剛訂親時(shí),他對(duì)我挺好的。 每次回我家,他都買好多...
    娰悅閱讀 1,375評(píng)論 40 47
  • 文/繆四兒 幾天后的一個(gè)晚上,我獨(dú)自睡在廚房的炕頭上;我娘做晚飯把炕燒的溫?zé)?,可夜半醒來總是覺得后背發(fā)冷。 我瑟縮...
    繆四兒閱讀 364評(píng)論 0 11
  • 今天大寒。 一年中最冷的時(shí)節(jié)到了,春天也快來了。 獨(dú)自坐在辦公室里,心如止水,思緒起航。 有時(shí),不折騰自己,不拼命...
    一簾思語閱讀 180評(píng)論 0 0

友情鏈接更多精彩內(nèi)容