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

PHP SPL 觀察者模式標準實作:SplSubject 與 SplObserver 介面完整範例

     編輯:PHP 相關知識

PHP 5.1+ 內建 SplSubject 與 SplObserver 介面,標準化觀察者模式實作。本文展示使用 SPL 介面建立 DemoSubject (被觀察者) 與 DemoObserver (觀察者) 的完整代碼,涵蓋 attach()/detach()/notify() 管理觀察者清單、狀態變更觸發通知、update() 接收推送資料,並解析 SPL 標準與自行定義介面的差異。

SPL 介面定義 (內建)

interface SplSubject {
    public function attach(SplObserver $observer);
    public function detach(SplObserver $observer);
    public function notify();
}

interface SplObserver {
    public function update(SplSubject $subject);
}

完整實作代碼

<?php
class DemoSubject implements SplSubject {
    private $observers = array();
    private $value;

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

    // 註冊觀察者
    public function attach(SplObserver $observer) {
        $this->observers[] = $observer;
    }

    // 移除觀察者
    public function detach(SplObserver $observer) {
        $idx = array_search($observer, $this->observers, true);
        if ($idx !== false) {
            unset($this->observers[$idx]);
        }
    }

    // 通知所有觀察者
    public function notify() {
        foreach ($this->observers as $observer) {
            // 推模式:傳遞主題自身,觀察者自行取值
            $observer->update($this);
        }
    }

    // 設定值並觸發通知
    public function setValue($value) {
        $this->value = $value;
        $this->notify();
    }

    public function getValue() {
        return $this->value;
    }
}

class DemoObserver implements SplObserver {
    public function update(SplSubject $subject) {
        // 觀察者從主題拉取所需資料 (拉模式)
        echo 'The new value is ' . $subject->getValue() . "\n";
    }
}

// 客戶端測試
$subject = new DemoSubject();
$observer = new DemoObserver();
$subject->attach($observer);
$subject->setValue(5);  // 輸出: The new value is 5
$subject->setValue(10); // 輸出: The new value is 10
$subject->detach($observer);
$subject->setValue(20); // 無輸出
?>

SPL 標準 vs 自定義介面對比

特性SPL 標準介面自定義介面 (Head First 範例)
介面名稱SplSubject / SplObserverSubject / Observer / DisplayElement
通知方法notify() 無參數notifyObservers() 無參數
更新方法update(SplSubject $subject)update($temp, $humidity, $pressure)
資料傳遞模式拉模式:觀察者從 Subject 取值推模式:Subject 推送資料給觀察者
觀察者管理attach/detach (單數)registerObserver/removeObserver
型別提示強制 SplObserver/SplSubject自定義介面
相容性PHP 內建,第三方庫可直接互操作專案內部使用

關鍵差異:拉模式 (SPL) vs 推模式 (自定義)

  • SPL 拉模式:notify() 不帶參數,update(SplSubject $subject) 由觀察者呼叫 $subject->getValue() 等方法主動取值。優點:觀察者按需取值,Subject 不需知道觀察者需要什麼資料。缺點:觀察者耦合 Subject 具體方法。
  • 自定義推模式:notifyObservers() 內部遍歷呼叫 $ob->update($temp, $humidity, $pressure) 直接推送資料。優點:觀察者完全被動,不依賴 Subject 介面。缺點:Subject 需知道觀察者需要什麼資料,或推送所有資料。

進階:多觀察者與選擇性通知

class AdvancedSubject implements SplSubject {
    private $observers = array();
    private $data = array();

    public function attach(SplObserver $observer) { ... }
    public function detach(SplObserver $observer) { ... }

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

    public function setData($key, $value) {
        $this->data[$key] = $value;
        $this->notify();
    }

    public function getData($key) {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }
}

class LoggerObserver implements SplObserver {
    public function update(SplSubject $subject) {
        // 記錄所有變更
        error_log("Data changed: " . json_encode($subject->getData()));
    }
}

class AlertObserver implements SplObserver {
    public function update(SplSubject $subject) {
        // 只關心特定閾值
        if ($subject->getData('temperature') > 100) {
            echo "ALERT: Temperature critical!\n";
        }
    }
}

總結

PHP SPL 提供標準化觀察者模式介面 SplSubject/SplObserver,採用拉模式 (notify 無參、update 取主題)。核心流程:Subject 維護觀察者陣列 → attach/detach 管理 → 狀態變更呼叫 notify() → 遍歷呼叫 update($this) → 觀察者從 Subject 取值。使用 SPL 介面可確保與第三方庫互操作性,是現代 PHP 專案實作觀察者模式的首選標準。

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