搜尋
首頁後端開發php教程了解觀察者模式

Understanding the Observer Pattern

核心要點

  • 觀察者模式是一種行為型設計模式,它在對象之間建立一對多的關係,當一個對象改變其狀態時,所有依賴對像都會自動收到通知並更新。
  • 該模式包含一個主題(或發布者)和觀察者(或訂閱者)。主題通知觀察者任何狀態變化,觀察者可以相應地採取行動。此模式促進鬆散耦合,使系統更靈活,更容易修改或擴展。
  • 觀察者類提供一個update()方法,主題調用該方法以通知其狀態變化。主題類定義主要方法:attach()detach()setState()notify(),用於管理觀察者並通知他們狀態變化。
  • 觀察者模式適用於一個對象的更改需要更改其他對象的情況,尤其是在要更改的對像數量未知時。它可以用於在相關對象之間保持一致性,而無需緊密耦合它們。例如,它用於將門戶的身份驗證機制與論壇軟件鏈接,允許用戶使用單個登錄名登錄兩者。

我最近被要求將第三方論壇軟件集成到現有的 Web 門戶中。問題是,這兩個應用程序都有各自獨立的身份驗證機制。從用戶的角度來看,理想情況下,用戶無需單獨登錄論壇即可登錄門戶。在這種情況下,我不希望不必要地修改論壇代碼,因為這會造成維護噩夢——我必須合併供應商的任何後續更新和錯誤修復,並小心避免覆蓋我自己的修改。這就是觀察者模式對我來說非常方便的地方。在本文中,我將向您展示如何實現觀察者模式。您將學習模式中各種類如何相互關聯作為主題和觀察者,主題如何通知觀察者其狀態的變化,以及如何在您自己的代碼中識別適合使用觀察者模式的場景。

觀察者模式

觀察者模式(也稱為發布-訂閱模式)是一種行為型設計模式,它定義對象之間的一對多關係,以便當一個對象改變其狀態時,所有依賴對像都會自動收到通知並更新。在我的例子中,我使用此模式將門戶的身份驗證機制與論壇軟件鏈接。登錄門戶的行為也會自動觸髮用戶登錄論壇。與其他對自身狀態感興趣的對象具有一對多關係的對象稱為主題發布者。其依賴對象稱為觀察者訂閱者。每當主題的狀態發生變化時,觀察者都會收到通知,並可以相應地採取行動。主題可以擁有任意數量的依賴觀察者,它會向這些觀察者發出通知,並且任意數量的觀察者都可以訂閱主題以接收此類通知。

觀察者類

觀察者類提供一個update()方法,主題將調用該方法以通知其狀態變化。在此示例中,我已將update()方法定義為具體方法。如果您願意,您可以在此處將該方法定義為抽象方法,然後在觀察者的子類中為其提供具體實現。

<?php
abstract class Observer
{
    public function __construct($subject = null) {
        if (is_object($subject) && $subject instanceof Subject) {
            $subject->attach($this);
        }
    }

    public function update($subject) {
        // 查找具有状态名称的观察者方法
        if (method_exists($this, $subject->getState())) {
            call_user_func_array(array($this, $subject->getState()), array($subject));
        }
    }
}

__construct()方法接受可觀察主題的實例,並將自身附加到主題——我稍後會講到。 update()方法檢索主題的當前狀態,並使用它來調用與狀態名稱相同的子類化觀察者方法。因此,在我的特定情況下,我需要將門戶現有的 Auth 類設為可觀察主題,並創建一個具體的觀察者子類來連接到論壇的身份驗證代碼。我的子類還需要使用主題的狀態來實現方法。

主題類

主題類也是一個抽像類,它定義了四個主要方法:attach()detach()setState()notify()。為方便起見,我還在此處添加了getState()getObservers()方法。

<?php
abstract class Subject
{
    protected $observers;
    protected $state;

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

    public function attach(Observer $observer) {
        $i = array_search($observer, $this->observers);
        if ($i === false) {
            $this->observers[] = $observer;
        }
    }

    public function detach(Observer $observer) {
        if (!empty($this->observers)) {
            $i = array_search($observer, $this->observers);
            if ($i !== false) {
                unset($this->observers[$i]);
            }
        }
    }

    public function getState() {
        return $this->state;
    }

    public function setState($state) {
        $this->state = $state;
        $this->notify();
    }

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


    public function getObservers() {
        return $this->observers;
    }
}

attach()方法將觀察者訂閱到主題,以便可以向其傳達任何狀態更改。 detach()方法將觀察者從主題中取消訂閱,以便它不再觀察主題的狀態更改。 setState()方法設置主題的當前狀態並調用notify()來更新觀察者,即向每個觀察者發布通知。 notify()方法依次通過迭代內部列表並調用每個成員的update()方法來更新每個已訂閱的對象。 getState()getObservers()方法只是返回當前主題的狀態和觀察者列表的輔助函數。

仔細觀察……整合在一起

現在有了觀察者和主題的抽象基類,我能夠將論壇軟件集成到現有的 Web 門戶中。我需要將門戶的 Auth 類設為可觀察主題,並在用戶登錄或註銷門戶時設置其可觀察狀態。

<?php
class Auth extends Subject
{
    function login() {
        // 执行登录身份验证的现有代码
        // ...

        // 向任何观察者发出信号,表明用户已登录
        $this->setState("login");
    }

    function logout() {
        // 执行用户注销时执行某些操作的现有代码
        // 例如销毁会话等...

        // 向任何观察者发出信号,表明用户已注销
        $this->setState("logout");
    }
}

我擴展了 Subject 類,以便 Auth 可觀察,然後在 login()logout() 方法中添加了對 setState() 的調用。為了對觀察者進行子類化,我創建了一個 Auth_ForumHook 類,該類負責調用論壇的 API 登錄和註銷函數。

<?php
class Auth_ForumHook extends Observer
{
    function login($subject) {
        // 调用论坛的 API 函数以登录用户
        // ...
    }

    function logout($subject) {
        // 调用论坛的 API 函数以注销用户
        // ...
    }
}

在代碼庫的其他地方,在實例化門戶的 Auth 類的地方,我將 Auth_ForumHook 實例附加到它,以便觀察者會收到 Auth 中任何狀態更改的通知。

<?php
abstract class Observer
{
    public function __construct($subject = null) {
        if (is_object($subject) && $subject instanceof Subject) {
            $subject->attach($this);
        }
    }

    public function update($subject) {
        // 查找具有状态名称的观察者方法
        if (method_exists($this, $subject->getState())) {
            call_user_func_array(array($this, $subject->getState()), array($subject));
        }
    }
}

除了準備抽象的 Observer 和 Subject 類之外,這就是我的額外編碼需求的全部內容。 Auth 的 login()logout() 方法觸發的任何狀態更改都會通知 Auth_ForumHook 觀察者,並自動登錄或註銷論壇中的用戶。要添加新的觀察者,例如,登錄跟踪器以記錄用戶何時登錄或註銷門戶,只需提供一個具體的 Observer 類並將其附加到 Auth 主題即可,而無需進一步修改現有的 Auth 對象的 login()logout() 方法。

總結

如果您有多個依賴於另一個對象的對象,並且需要在該對象的狀態發生變化時執行操作,或者一個對象需要通知其他對象而不知道它們是誰或有多少個,那麼觀察者模式是一個合適的適用設計模式。在本文中,我向您展示了基本的主題-觀察者模式,並提供了具體的示例,說明如何使用這種行為模式輕鬆擴展現有類的功能,而無需緊密耦合任何新的需求。此模式使您能夠在相關和依賴對象之間實現更高水平的一致性,而不會犧牲代碼的可重用性。

圖片來自 JPF / Shutterstock

(後續的FAQs部分,由於篇幅過長,已省略。核心內容已在上面重新組織和潤色。)

以上是了解觀察者模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在Laravel中使用Flash會話數據在Laravel中使用Flash會話數據Mar 12, 2025 pm 05:08 PM

Laravel使用其直觀的閃存方法簡化了處理臨時會話數據。這非常適合在您的應用程序中顯示簡短的消息,警報或通知。 默認情況下,數據僅針對後續請求: $請求 -

php中的捲曲:如何在REST API中使用PHP捲曲擴展php中的捲曲:如何在REST API中使用PHP捲曲擴展Mar 14, 2025 am 11:42 AM

PHP客戶端URL(curl)擴展是開發人員的強大工具,可以與遠程服務器和REST API無縫交互。通過利用Libcurl(備受尊敬的多協議文件傳輸庫),PHP curl促進了有效的執行

簡化的HTTP響應在Laravel測試中模擬了簡化的HTTP響應在Laravel測試中模擬了Mar 12, 2025 pm 05:09 PM

Laravel 提供简洁的 HTTP 响应模拟语法,简化了 HTTP 交互测试。这种方法显著减少了代码冗余,同时使您的测试模拟更直观。 基本实现提供了多种响应类型快捷方式: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

在Codecanyon上的12個最佳PHP聊天腳本在Codecanyon上的12個最佳PHP聊天腳本Mar 13, 2025 pm 12:08 PM

您是否想為客戶最緊迫的問題提供實時的即時解決方案? 實時聊天使您可以與客戶進行實時對話,並立即解決他們的問題。它允許您為您的自定義提供更快的服務

解釋PHP中晚期靜態結合的概念。解釋PHP中晚期靜態結合的概念。Mar 21, 2025 pm 01:33 PM

文章討論了PHP 5.3中介紹的PHP中的晚期靜態結合(LSB),允許靜態方法的運行時間分辨率調用以更靈活的繼承。 LSB的實用應用和潛在的觸摸

如何註冊和使用Laravel服務提供商如何註冊和使用Laravel服務提供商Mar 07, 2025 am 01:18 AM

Laravel的服務容器和服務提供商是其架構的基礎。 本文探討了服務容器,詳細信息服務提供商創建,註冊,並通過示例演示了實際用法。 我們將從OVE開始

PHP記錄:PHP日誌分析的最佳實踐PHP記錄:PHP日誌分析的最佳實踐Mar 10, 2025 pm 02:32 PM

PHP日誌記錄對於監視和調試Web應用程序以及捕獲關鍵事件,錯誤和運行時行為至關重要。它為系統性能提供了寶貴的見解,有助於識別問題並支持更快的故障排除

自定義/擴展框架:如何添加自定義功能。自定義/擴展框架:如何添加自定義功能。Mar 28, 2025 pm 05:12 PM

本文討論了將自定義功能添加到框架上,專注於理解體系結構,識別擴展點以及集成和調試的最佳實踐。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
2 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
2 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器