interface, Oberver

RSSでチェックしているblogに、ActionScriptの機能とデザインパターンの一つであるObserverパターンを勉強するのに良さそうなエントリがあったので、週末にちょっと時間を割いて勉強してみました。

言語に依らず、interfaceというものを自分で使ったことが無かった。とくにinterfaceじゃなくても継承でいいじゃない、という考え方でした。
でも、interfaceの必要性も理解しておきたい、というところもあり、今回勉強してみることにしたのです。
で、上記のblogエントリを読みつつ、自分で考えながらコードを書き、AS3で実装してみました。以下のコードを読むのも良いですが、上記ブログを参考にしつつ、自分で書かれるのも良いかと思います。

監視される基底クラス作成

Observerパターンということで、何かを監視されるる側のクラスが必要ですが、AS3でいじりやすくするためにSpriteを派生させたSubjectSpriteと名付けたクラスを用意します。
オブザーバを登録するメソッドと、登録されたオブザーバのupdateメソッドを呼び出すメソッドの二つだけを実装しています。

public class SubjectSprite extends Sprite {
  public var mObservers:Array  = [];  // オブザーバの配列.
  
  /**
   * オブザーバを追加.
   */
  public function addObserver( observer:IObserver ) :void{
    mObservers.push( observer );
  }
  
  /**
   * 全てのオブザーバに自分自身の情報を通知.
   */
  protected function notifyObservers() :void{
    for each ( var observer:IObserver in mObservers ) {
      observer.update( this );
    }
  }
}

ソースを見て分かるように、このクラスに登録するオブザーバはIObserverを実装する必要(implements)があります。

監視する側のもとを作成

続いて、SubjectSpriteを監視するクラスの基本定義として、interface定義を行います。

public interface IObserver {
  function update( target:SubjectSprite ) :void;
}

次にIObserverを実装するクラスを定義します。
今回は簡単に理解するためにマウス座標を取得してtraceする監視クラスを作成します。

public class MouseXObserver implements IObserver {
  public function update( target:SubjectSprite ) :void
  {
    if ( target.mouseX < 100 ){
      trace( "MouseX[" + target.mouseX + "]" );
    }
  }
}

また、ほとんど同じ内容でMouseYObserverを実装します。
場合によっては、クリック時や、アルファ値の変化などに上記のようなメソッドをフックさせると良いかもしれません。
この「どういうタイミングで、どういう処理にオブザーバの処理をフックさせるか」というのがobserverパターンの肝のような気がしますが、こればかりは何度もプロジェクトで使わないと勘所がつかめないですね。

テストクラスを作成

さて、最後にテストを行います。以上のモノを使う側のクラスは次のようになります。

public class TestObserver extends SubjectSprite{
  public function TestObserver(){
    addObserver( new MouseXObserver() );
    addObserver( new MouseYObserver() );
    
    addEventListener( Event.ENTER_FRAME, process );
  }
  
  private function process( e:Event ) :void{
    // オブザーバに通知.
    notifyObservers();
  }
}

これをTestObserver.asとして保存し、パブリッシュします。マウスイベント処理を把握してその様子がtraceで出力されました。

まとめ

以上のコードを書いてエントリを書いてたら、Observerパターンがつかめ、interfaceの使用例が一つ理解できた。
今回のようなObserverパターンの場合、別にinterfaceを使わなくても、クラスの継承でも良いような気もしますが、やはり何となくinterfaceの方があっているような気がします。もしかしたら、Stateパターンもinterfaceが向いているかもしれません。
この「何となく〜と思う」を確信に変えるには、何度か試行錯誤をくり返すのが必要だろうと思う。もしかしたらその過程で別の実装方法が適切だと分かるかもしれないが、それを自分で体験できたことが重要だ。
こういうinterfaceを使う場面を表すのに、何か良い表現はないだろうか。「○○が△△のときはinterfaceを使うべき」といういうような。
しかし、interface機能やObserverパターンといったプログラミング技術を、見た目や意味的にもチェックしやすいコードを書きやすいActionScript3.0は素晴らしいですね。

NHKためしてガッテン〈12〉―雑学読本

NHKためしてガッテン〈12〉―雑学読本

ガッテンしていただけましたでしょうか。