LoginSignup
6
6

More than 5 years have passed since last update.

PHPで使うGoFパターン ひとり Advent Calendar - オブザーバー

Posted at

オブザーバーってなに?

オブザーバーとか大仰な名前が付いていますが要はカスケード更新したりするような時に使うパターンです。オブザーバーは日本語で言うと「観察者」くらいの意味になりますか。GUIやDOMなんかのフレームワークではよく使ってるんじゃないでしょうか? DOMのバブリングもこれだと思います。

オブザーバーの構造

  • ISubject - オブザーバーを使う側のインターフェース
  • Subject - ISubjectを実装した実クラス
  • IObserver - 通知を受け取るオブザーバー
  • Observer - IObserver を 実装した実クラス
<?php
interface ISubject {
  public function add ( $observer );
  public function remove ( $observer );
  public function notify ( $e );
}

interface IObserver {
  public function recieve ( $music );
}

class Radio implements ISubject {
  private $_List      = array ();
  private $_MusicList = array ();
  public function __construct () {
  }

  public function add ( $observer ) {
    if ( !( $observer instanceof IObserver ) )
      throw new Exception ( '無理じゃね?' );
    $this->_List[] = $observer;
  }

  public function remove ( $observer ) {
    $tmp = $this->_List;
    foreach ( $tmp as $obj ) {
      if ( $observer != $obj ) {
        $this->_List[] =$obj;
      }
    }
  }

  public function notify ( $e ) {
    foreach ( $this->_List as $obj ) {
      $obj->recieve ( $e );
    }
  }

  public function broadCast ( $music ) {
    $this->_MusicList[] = $music;
    $this->notify ( $music );
  }

  public function talk () {
    $this->notify ( 'DJの喋り' );
  }
}

class Listner implements IObserver {
  private $_Name = null;
  public function __construct ( $name ) {
    $this->_Name = $name;
  }

  public function recieve ( $music ) {
    print "$this->_Name さんが " . $music . " を聞きました\n";
  }
}

$radio = new Radio ();
$radio->add ( new Listner ( 'Larry' ) );
$radio->add ( new Listner ( 'Gates' ) );
$radio->add ( new Listner ( 'Jobs' ) );
$radio->broadCast ( 'Flim / Aphex Twin ' );
$radio->broadCast ( 'Journey to reedham / SquarePusher' );
$radio->talk ();

例では少なかったですがSubjectが何かするたびに、
必要があれば、ちょくちょくnotifyをキックするイメージです。
notifyで渡す引数は、もっと汎用的に状態を通知出来るオブジェクトとかでも良いです。
例えば、JavaScriptのイベントの仕組みでは event というオブジェクトだったりします。

実際どうなの?

パターンと言うには単純で適用範囲も実アプリでは少なそうに見えますが、
例えば、ORマッパーでキー値が更新された時にnotifyして連鎖更新するの
なんかにも使えますね。
Unitテストは割とし易いと思います。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6