blog

Observer パターンの PHP デザインパターン

アクションは observed インターフェイスを実装しています。 まず register メソッドを実装し、オブザーバを渡して配列に詰め、notify メソッドを実装します。 ここでは3つのメソッド...

Jul 21, 2020 · 4 min. read
シェア

使用例

プロジェクト・マネージャーがログイン・インターフェースを書かせ、それをクリックして書いたとします。

  • 翌日、ログイン回数を追加し、その後に次のコードを追加します。
  • 3日目、ランディングエリアを裁断し、その後ろにコードを追加。
  • splsubjectインターフェイス - オブザーバ
  • Observerインターフェイス - オブザーバ

プロジェクトの結合度を高く保ち、結合度を低く保つ必要がある場合は、オブザーバー・パターンを使うことができます。

概念

観察者、オブザーバーは、まず第一に、観察されるという役割があるはずで、それは唯一無二のものです。そして、彼女を見るオブザーバーは無数にいるはずで、いわば、一人の人を見ている人の集まりです。

コードサンプル

  • SplObjectStorageオブジェクト - コンテナ
// テーマインターフェイス
interface Subject{
 public function register(Observer $observer);
 public function notify();
}
// オブザーバインタフェース
interface Observer{
 public function watch();
}

Subjectは観察される人、Observerは見る人(観察者)。

オブザーバ

// オブザーバ
class Action implements Subject{
 public $_observers=array();
 public function register(Observer $observer){
 $this->_observers[]=$observer;
 }
 
 public function notify(){
 foreach ($this->_observers as $observer) {
 $observer->watch();
 }
 
 }
 }

Actionはobservedインターフェイスを実装し、オブザーバーとなり、次に$_observersの配列を定義します。次にnotify()メソッドを実装します。notify()メソッドはコンテナの配列を走査し、それぞれのオブザーバーに対してwatch()メソッドを実行します。

オブザーバ

//  
class Cat implements Observer{
 public function watch(){
 echo "Cat watches TV<hr/>";
 }
 }
 class Dog implements Observer{
 public function watch(){
 echo "Dog watches TV<hr/>";
 }
 }
 class People implements Observer{
 public function watch(){
 echo "People watches TV<hr/>";
 }
 }

ここでは3つのオブザーバーが定義されており、いずれもObserverインターフェイスを実装しています。 前のSubjectでは、各オブザーバーのwatch()メソッドをラウンドロビン方式で呼び出しますので、各オブザーバーのwatch()メソッドを実装する必要があります。

をコールします。

// アプリケーションの例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();

最初にオブザーバ・オブジェクトを生成し、register()メソッドを実行して各オブザーバをコンテナ配列に入れ、最後にnotify()メソッドを実行してすべてのオブザーバに自身のメソッドを実行するように通知します。

PHP には observer パターンがネイティブに組み込まれています。

PHP には独自のオブザーバー・パターンがあります。

  • splsubject インターフェース - 観測
  • オブザーバーインターフェース - オブザーバー
  • SplObjectStorage オブジェクト - コンテナ

まず、ユーザー・ログイン・クラスがあります。

class user{
 public function login()
 {
 	echo 'ログインが完了した
 }

被観察者となるために splsubject インターフェースを実装させましょう。

  • まずコンストラクタで、新しい SplObjectStorag() オブジェクトを作成してプロパティに代入します。
  • オブザーバーを登録する attach() メソッドを実装します。
  • オブザーバを削除するためのdetach()メソッドの実装
  • コンテナを走査し、各オブザーバの update メソッドを呼び出すために使用される notify() メソッドを実装します。
  • rewind メソッドはコンテナのポインタを最初にリセットし、valid メソッドはコンテナの走査が完了したかどうかを検出してブール値を返し、current メソッドは現在のオブザーバを取得し、next メソッドはポインタを 1 つ戻します。
  • イベントが完了したことをオブザーバに通知するために notify() を呼び出すように login() メソッドを変更します。
class user implements splsubject{
 protected $observer = null;
 public function __construct()
 {
 $this->observer = new SplObjectStorage();
 }
 public function login()
 {
 $this->notify();
 echo 'ログインが完了した;
 }
 public function attach(SplObserver $observer)
 {
 $this->observer->attach($observer);
 }
 public function detach(SplObserver $observer)
 {
 $this->observer->detach($observer);
 }
 public function notify()
 {
 $this->observer->rewind();
 while ($this->observer->valid())
 {
 $observer = $this->observer->current();
 $observer->update($this);
 $this->observer->next();
 }
 }
}

オブザーバ

各オブザーバは SplObserver インターフェイスと update() メソッドを実装しています。

class cat implements SplObserver {
 public function update(SplSubject $subject)
 {
 echo '子猫が少し鳴く;
 }
}
class dog implements SplObserver {
 public function update(SplSubject $subject)
 {
 echo 'パピーハウルの;
 }
}

アプリケーションは

// リアルタイム観測
$user = new user();
$user->attach(new cat());
$user->attach(new dog());
$user->login();
Read next

032 JavaEEに関する質問: Spring

導入\n\nSpring IOCとは何ですか?\nIOC:\nInversion of Controlの略で、Spring IOCはオブジェクトの作成と管理を行います。IOCはオブジェクトを組み立て、構成し、依存性注入を通してライフサイクル全体を管理します。\n

Jul 20, 2020 · 5 min read