首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 觀察者模式實作:基於 SPL 接口的完整範例

     編輯:PHP 綜合知識

模式結構

  • SplSubject —— 被觀察者介面:attach()、detach()、notify()。
  • SplObserver —— 觀察者介面:update(SplSubject $subject)。
  • SplObjectStorage —— 內建物件集合,自動處理附加/移除/迭代。

完整程式碼

<?php
// 被觀察者
class Observed implements SplSubject {
    protected $_name;
    protected $_observers;

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

    public function attach(SplObserver $observer) {
        $this->_observers->attach($observer);
    }

    public function detach(SplObserver $observer) {
        $this->_observers->detach($observer);
    }

    public function notify() {
        foreach ($this->_observers as $observer) {
            $observer->update($this);
        }
    }

    // 業務方法:設定名稱並通知
    public function setName($name) {
        $this->_name = $name;
        $this->notify();
    }

    public function getName() {
        return $this->_name;
    }

    // 另一個業務方法:設定年齡並單獨通知
    public function setAge($age) {
        $this->age = $age;
        foreach ($this->_observers as $observer) {
            $observer->showAge($this->_name, $this->age);
        }
    }
}

// 觀察者
class Observer implements SplObserver {
    public function update(SplSubject $subject) {
        $this->showMessage($subject);
    }

    public function showMessage(SplSubject $obj) {
        $user = $obj->getName();
        if ($user === 'admin') {
            echo "您好, $user 歡迎進入管理後台<br/>";
        } else {
            echo "你好, '$user' 你已被加入用戶列表<br/>";
        }
    }

    public function showAge($name, $age) {
        echo "<script>alert('$name 的年齡是: $age')</script>";
    }
}

// 使用示範
$subject = new Observed();
$observer = new Observer();
$subject->attach($observer);

$subject->setName('張三');  // 觸發 notify() → update() → showMessage()
$subject->setName('admin'); // 不同歡迎語
$subject->setAge(24);       // 直接呼叫觀察者的 showAge()

執行流程圖解

  1. $subject->attach($observer) 將觀察者存入 SplObjectStorage。
  2. 呼叫 setName() → 內部 $this->notify()。
  3. notify() 迭代所有觀察者,呼叫 $observer->update($this)。
  4. Observer::update() 轉呼叫 showMessage() 完成具體邏輯。

關鍵優勢

  • 解耦:Subject 不需知道 Observer 具體類別,僅依賴介面。
  • 動態增減:運行時可 attach/detach,支援插件式架構。
  • 標準化:使用 SPL 介面,程式碼可讀性高、易維護。

實戰應用場景

  1. 事件驅動系統(訂單建立 → 發送郵件、扣庫存、記錄日誌)。
  2. 快取失效通知(資料更新 → 通知多台前端清除快取)。
  3. 日誌/監控掛鉤(錯誤發生 → 寫入檔案、發送 Slack、存入資料庫)。

擴展提示

若需優先級或一次性觀察者,可自行擴充 SplObjectStorage 或改用 SplPriorityQueue 管理觀察者列表。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved