2013年5月17日金曜日

design patterns – observer


オブザーバー

さて、今度はオブザーバーについて説明します。オブザーバーパターンは、JavaScriptで最もよく使用されているパターンの1つです(Publish/Subscribeとも呼びます。省略形はPub/Sub)。これは、DOM要素のイベント処理は、(あらゆる規模のJavaScriptアプリケーションで非常によく見られることですが)オブザーバーパターン経由で実行されるからです。

オブザーバーパターンの説明

オブザーバーパターンはシンプルで、2つのエンティティで構成されます。監視対象のオブジェクト(「監視対象」と呼ばれる)と、監視対象を監視するオブジェクト(「オブザーバー」と呼ばれる)です。どちらも図1に示されています。DOMイベントの場合は、オブザーバーオブジェクトが特定のインターフェイスを採用することを要求しないため、JavaScriptでよくあるように、オブザーバーは単なるコールバック関数です。大半の言語では関数/メソッドはファーストクラスオブジェクトではなく渡せないため、このような使い方はできませんが、JavaScriptはこの点においては非常に幸運です。
図1.オブザーバーパターンの構造
図1.オブザーバーパターンの構造

オブザーバーの種類

オブザーバーパターンの実装方法には、プッシュとプルの2つがあります。プッシュメソッドでは、オブザーバーは監視対象オブジェクトをサブスクライブし、監視対象に注目すべき事象が発生した場合にオブザーバーに連絡して知らせます。これが、DOMイベントの挙動です。プルメソッドでは、監視対象は、オブザーバーの持つサブスクリプションリストに追加されます。定期的に、または指定されたときに、オブザーバーは、監視対象内で変更が発生したかどうかをチェックし、変更があった場合はその変更に反応して何らかの処理を実行します。多くのデスクトップソフトウェアで、アップデートはこのように動作します。アプリケーションは、起動時にアップデートがあるかどうかサーバーをチェックし、アップデートが見つかった場合は、アップデートのインストールを開始します。

プッシュオブザーバー

まず、プッシュメソッドを介したオブザーバーパターンのシンプルな例の構築について、ひと通り見てみましょう。ここではプルメソッドの例は紹介しませんが、それはほとんどのプルメソッドがサーバーとのやり取り(AJAXを使ってサーバーに照会するだけ)に使用されるからです。フロントエンドWeb開発におけるプルメソッドの使用は限定的です。
var Observable = function() { this.subscribers = []; } Observable.prototype = { subscribe: function(callback) { // Just add the callback to the subscribers list this.subscribers.push(callback); }, unsubscribe: function(callback) { var i = 0, len = this.subscribers.length; // Iterate through the array and if the callback is // found, remove it from the list of subscribers. for (; i < len; i++) { if (this.subscribers[i] === callback) { this.subscribers.splice(i, 1); // Once we've found it, we don't need to // continue, so just return. return; } } }, publish: function(data) { var i = 0, len = this.subscribers.length; // Iterate over the subscribers array and call each of // the callback functions. for (; i < len; i++) { this.subscribers[i](data); } } }; // The observer is simply a function var Observer = function (data) { console.log(data); } // Here's where it gets used. observable = new Observable(); observable.subscribe(Observer); observable.publish('We published!'); // 'We published!' will be logged in the console observable.unsubscribe(Observer); observable.publish('Another publish!'); // Nothing happens because there are no longer any subscribed observers
では、順を追って少しずつ見ていきましょう。まず、Observableコンストラクターを作成します。このコンストラクターは、サブスクライバー/オブザーバーを格納する空の配列を作成するだけです。次に、subscribeunsubscribepublishというプロトタイプ関数を作成します。これらの3つの関数は、すべてのタイプのプッシュ監視対象に必要です。もちろん、これらの関数の名前は変更できます。subscribe関数は、オブザーバー関数をサブスクライバーの配列に単に追加します。unsubscribe関数は、指定されたオブザーバーを検索し、リストから削除します。publishは、オブザーバーのリスト全体を反復処理し、実行します。
プロトタイプを介してではなくオブジェクトリテラルを使用してObservableオブジェクトを作成する場合、mixinsを使用して任意のオブジェクトを監視対象にできます。オブザーバーパターンとプルメソッドを一緒に使用する方法や、オブザーバーパターンに関する一般的な情報をもう少し詳しく知りたい場合には、筆者のJavaScriptブログで「JavaScript Design Patterns: Observer」の投稿をお読みください。

0 件のコメント: