Sep 11, 2008

Observerパターン

前から興味のあったデザインパターンの本を購入。(→ Head Firstデザインパターン)。Javaは知識レベルでしか知らないので難しいかと思ったが、以外にいけた。まだ2章までしか読んでないけどおもしれえ。で、その2章のお題目であるObserverパターンがさらにおもしれえ。簡単に言うと、「何か変化がおきたときに、複数のオブジェクトに通知する」っての(詳しくはWikiへ)。

例えば、「定期的にサーバにデータを取得しにいって、更新があった場合に複数のオブジェクトに一括で更新を通知するオブジェクト」なんてのは、Ajaxを使ったWebアプリケーションだったらよくある。こういうのにまさしく使えるパターン。これを実装するとしたら、

/*-------------------------------------------------------*/
/* 更新を通知してくれるクラス
/* デザインパターンだと、サブジェクトと呼ぶ。
/*-------------------------------------------------------*/
var Subject = function() {
  this.list = [];
};
Subject.prototype = {
  // 通知対象を登録するメソッド
  register: function(observer) {
    // 通知を受けるメソッドはupdateメソッドを実装している必要がある。
    // Javaだと、updateの実装を強要できる、インターフェースという機能があるけど、
    // JavaScriptはないので、ここでupdateが実装されているかチェックする。
    if (!observer.update)
      throw new Error("this object doesn't have update method.");

    // リストに登録
    var list = this.list;
    for (var i=0,len=list.length; i<len; i++)
      if (list[i] === observer)
        return;
    list.push(observer);
  },

  // 通知対象を削除するメソッド
  remove: function(observer) {
    var list = this.list;
    for (var i=0,len=list.length; i<len; i++)
      if (list[i] === observer)
        list.splice(i, 1); return;
  },

  // 通知メソッド
  //(通知される側はupdateというメソッドを実装する必要がある)
  notify: function(data) {
    var list = this.list;
    for (var i=0,len=list.length; i<len; i++)
      list[i].update(data);
  }
}

更新を受け取る側は、

/*-------------------------------------------------------*/
/* 更新を受け取るクラス
/* デザインパターンだと、オブザーバーと呼ぶ。
/*-------------------------------------------------------*/
var Observer = function(){};
Observer.prototype = {
  // 更新通知をお願いするメソッド
  subscribe: function(subject) {
    subject.register(this);
  },
  // 更新通知をやめてもらうメソッド
  unsubscribe: function(subject) {
    subject.remove(this);
  }
}

使い方は、

var sub = new Subject();
sub.change = function() {
  var data = "hogehoge";
  if (/* dataが更新されていたら */) {
    this.notify(data);
  }
}

var obs = new Observer();
obj.update = function(data) {
  // 実装
}
obs.subscribe(sub);

みたいになる。そうすると、sub.change()で更新を検知すると、登録されているオブザーバーにupdateメソッドを通して更新を通知する。

実際にこのコードを使ったサンプルはココ(サーバーから定期的に時間を取得し、複数の方法で表示するようなの)。

Posted at 02:18 in | WriteBacks (0) | Edit
WriteBacks
TrackBack ping me at
http://thethirdshuren.org/blog/JavaScript/observer.trackback
Post a comment

writeback message: Ready to post a comment.