ホームページ >バックエンド開発 >PHPチュートリアル >オブザーバーパターンを理解する

オブザーバーパターンを理解する

Jennifer Aniston
Jennifer Anistonオリジナル
2025-02-28 09:14:19991ブラウズ

Understanding the Observer Pattern

コアポイント

  • オブザーバーパターンは、オブジェクトが状態を変更すると、すべての依存オブジェクトが自動的に通知および更新される動作デザインパターンです。
  • このモードには、トピック(またはパブリッシャー)とオブザーバー(またはサブスクライバー)が含まれています。被験者は、観察者にステータスの変化を通知し、オブザーバーはそれに応じて行動できます。このモードは、ゆるい結合を促進し、システムをより柔軟にし、変更または拡張しやすくします。
  • オブザーバークラスは、被験者がその状態の変更を通知するために呼び出す
  • 方法を提供します。トピッククラスを定義する主な方法:update()attach()detach()、およびsetState()は、オブザーバーを管理し、ステータスの変更を通知するために使用されます。 notify()
  • オブザーバーモードは、1つのオブジェクトの変更が他のオブジェクトの変更が必要な状況に適しています。特に変更するオブジェクトの数が不明な場合。関連するオブジェクトをしっかりと結合せずに、関連するオブジェクト間の一貫性を維持するために使用できます。たとえば、ポータルの認証メカニズムをフォーラムソフトウェアにリンクするために使用され、ユーザーが単一のログインで両方にログインできるようにします。
最近、サードパーティフォーラムソフトウェアを既存のWebポータルに統合するように求められました。問題は、両方のアプリケーションに独自の独立した認証メカニズムがあることです。ユーザーの観点からは、理想的には、ユーザーはフォーラムに個別にログインすることなく、ポータルにログインできます。この場合、メンテナンスの悪夢を作成するため、フォーラムコードを不必要に変更したくありません。ベンダーからの後続の更新とバグ修正をマージし、自分の変更を上書きしないように注意してください。これは、オブザーバーモードが私にとって非常に便利なところです。この記事では、オブザーバーパターンを実装する方法を紹介します。パターン内のさまざまなクラスがトピックとオブザーバーとして互いにどのように関連しているか、トピックがオブザーバーに状態の変化をどのように通知するか、および独自のコードでオブザーバーパターンを使用するのに適したシナリオを識別する方法を学びます。

オブザーバーモード

オブザーバーパターン(パブリッシュサブスクライブパターンとも呼ばれます)は、オブジェクト間の1対多くの関係を定義する行動設計パターンであり、オブジェクトが状態を変更すると、すべての従属オブジェクトが自動的に通知され、更新されます。私の場合、このモードを使用して、ポータルの認証メカニズムをフォーラムソフトウェアとリンクしました。ポータルにログインする動作は、ユーザーがフォーラムにログインするように自動的にトリガーされます。自分の状態に興味のある他のオブジェクトと1対多の関係を持つオブジェクトは、

トピックまたは出版社と呼ばれます。その依存性オブジェクトは、オブザーバーまたはsubscriberと呼ばれます。被験者の状態が変化するたびに、オブザーバーに通知され、それに応じて行動できます。トピックには、それらのオブザーバーに通知を送信する任意の数の依存的なオブザーバーを持つことができ、そのような通知を受信するためにトピックを購読することができます。

オブザーバーカテゴリ

オブザーバークラスは、被験者が状態の変更を通知するために呼び出す

メソッドを提供します。この例では、特定の方法としてupdate()メソッドを定義しました。必要に応じて、ここでメソッドを抽象的な方法として定義し、オブザーバーのサブクラスで具体的な実装を提供できます。 update()

<code class="language-php"><?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));
        }
    }
}</code>

メソッドは、観察可能なトピックのインスタンスを受け入れ、トピックに添付します。後で説明します。 __construct()メソッドは、トピックの現在の状態を取得し、それを使用して、同じ状態名でサブクラス化されたオブザーバーメソッドを呼び出します。したがって、私の特定のケースでは、ポータルの既存の認証クラスを観察可能なトピックとして作成し、具体的なオブザーバーサブクラスを作成して、フォーラムの認証コードに接続する必要があります。私のサブクラスは、トピックの状態を使用してメソッドを実装する必要もあります。 update()

テーマカテゴリ 件名クラスは、

attach()detach()setState()の4つの主要な方法を定義する抽象クラスでもあります。便利なため、ここにnotify()およびgetState()メソッドも追加しました。 getObservers()

<code class="language-php"><?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;
    }
}</code>

メソッドは、状態の変更を伝えることができるように、オブザーバーをトピックに購読します。 attach()メソッドは、トピックのオブザーバーを登録解除して、トピックの状態の変化を観察しなくなるようにします。 detach()メソッドは、トピックの現在の状態を設定し、setState()を呼び出して、オブザーバーを更新します。つまり、各オブザーバーに通知を発行します。 notify()メソッドは、内部リストを繰り返し、各メンバーのnotify()メソッドを順番に呼び出すことにより、各購読されたオブジェクトを更新します。 update()およびgetState()メソッドは、現在のトピックとオブザーバーリストのステータスを返すヘルパー関数にすぎません。 getObservers()

慎重に追加...一緒に統合します

オブザーバーとトピックの抽象的なベースクラスを使用して、フォーラムソフトウェアを既存のWebポータルに統合することができました。ポータルの認証クラスを観察可能なトピックに設定し、ユーザーがポータルにログアウトするかログアウトするときに観測可能な状態を設定する必要があります。

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

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

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

        // 向任何观察者发出信号,表明用户已注销
        $this->setState("logout");
    }
}</code>
authが観察可能になるようにサブジェクトクラスを拡張し、

およびlogin()メソッドでlogout()への呼び出しを追加しました。オブザーバーをサブクラス化するために、フォーラムのAPIログインおよびログアウト関数を呼び出す責任のあるauth_forumhookクラスを作成しました。 setState()

ポータルのAUTHクラスがインスタンス化されているコードベースの
<code class="language-php"><?php
class Auth_ForumHook extends Observer
{
    function login($subject) {
        // 调用论坛的 API 函数以登录用户
        // ...
    }

    function logout($subject) {
        // 调用论坛的 API 函数以注销用户
        // ...
    }
}</code>
その他は、auth_forumhookインスタンスを添付して、オブザーバーに認証の状態の変更を通知します。

<code class="language-php"><?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));
        }
    }
}</code>

これは、抽象的なオブザーバーとサブジェクトクラスを準備する以外に、すべての追加のコーディングニーズです。 AUTHのlogin()およびlogout()メソッドによってトリガーされる状態の変更は、auth_forumhookオブザーバーに通知し、フォーラムのユーザーから自動的にログインまたはログアウトします。たとえば、新しいオブザーバーを追加するには、トラッカーにログインして、ユーザーがポータルをログインまたはログアウトしたときに記録するには、特定のオブザーバークラスを提供し、既存の認証オブジェクトのlogin()およびlogout()メソッドをさらに変更せずにAUTHトピックに添付します。

概要

別のオブジェクトに依存し、そのオブジェクトの状態が変更されたときに操作を実行する必要がある複数のオブジェクトがある場合、または1つのオブジェクトが誰またはいくつのものであるかを知らずに他のオブジェクトに通知する必要がある場合、オブザーバーパターンは適切で適用可能なデザインパターンです。この記事では、基本的なトピック観察パターンを紹介し、新しい要件を緊密に結合せずに、この動作パターンを使用して既存のクラスの機能を簡単に拡張する方法の具体的な例を提供します。このパターンを使用すると、コードの再利用性を犠牲にすることなく、関連するオブジェクトと従属オブジェクトの間でより高いレベルの一貫性を実現できます。

JPF / ShutterStockの写真

(記事の長さのために、後続のFAQSセクションは省略されています。コアコンテンツは再編成され、磨かれています。)

以上がオブザーバーパターンを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。