読書ノート-javascriptデザインモデル-観察者モード
13656 ワード
イベント駆動の環境において、例えばブラウザのようなユーザの関心を継続的に求める環境において、観察者モードは、管理者とその任務(正確には、対象とその行為と状態との関係)との関係のための強力なツールである.javascriptを使うと、このモードの本質はプログラムの中のある対象の状態を観察し、変化が発生した時に通知することができるということです.
観察者モードには観察者と観察者の二つの役割が存在する.発表者と購読者と呼ばれることもあります.このようなモードはjavascriptの中にいくつかの異なる実現方法があります.以下ではその中のいくつかの実現方法を考察します.
パターンの実践:
javascriptには様々な方法があります.発表者-購読者モードを実現できます.これらの例を展示する前に、まず各種の役割の出演者(対象)とその行為(方法)が準備されていることを確認します.購読者は購読と購読ができます.彼らはまだ受け取っています.彼らは「人から送る」と「自分で取る」の間で選択できます. 発表者は投函を担当する.彼らは「送り出す」と「もらう」の間で選択できます. 以下は発表者と購読者との間のインタラクティブプロセスのトップの例である.
上のコードは新しい観察対象を作成しました.3つの例の方法があります.subscribe Customer、unSubscribeCustomerとdeliver.subscribe Cusstomer法は,ある購読者のフィードバック関数をパラメータとする.deliverメソッドは、呼び出し中にこれらのコールバック関数によってデータを各購読者に送信します.
次の例は同じ問題を処理しますが、発表者と購読者の間のインタラクティブな方式は違います.
このクラスの発表者はピュアブルースターの例です.彼はdeliverの方法を持っています.予約者の関数としてはsubscribeとunsubscribeの2つの方法がある.予約者は普通のフィードバック関数です.この二つの方法はFunctionのprototypeを拡張することによって追加されました.次は必要なAPIを一歩ずつ構築します.
観察者APIを構築する:
deliver方法は、thisを戻り値として使用するので、この方法をチェーン式で呼び出すことができます.
次は購読者の購読能力を与えることです.
someもjavascript 1.6の中で新しく増加した配列方法で、それは一つのコールバック関数をパラメータとして、そして一つ一つ配列の各要素にアクセスして、それをパラメータとしてそのコールバック関数を呼び出します.少なくとも一回の呼び出し関数があればtrueに戻ります.some方法はtureに戻ります.そうでなければ、some方法はfalseに戻ります.subscribeは、someメソッドの戻り値をalreadyExistsに割り当て、この変数の値に基づいて指定された投稿者に購読者を追加するかどうかを決定する.最後にsubscribe方法はthisに戻り、チェーン呼び出しをサポートします.
unsubscribe方法は、イベントの投稿者の観察を停止するために、購読者のために使用できる.
インスタンスアニメーション:
アニメーションは、アプリケーションで観察できるオブジェクトを実現するための良いスタートラインです.まばたきの間に、少なくとも3つの観察できる瞬間を思いつくことができます.開始、終了、進行中です.この例では、私たちはそれぞれワンストップ、onComplette、onTweenと呼びます.以下のコードは前に作成したPublisherツールでこれらのイベントを実現する過程を示しています.
DOMシナリオプログラミング環境における高レベルイベントモードでは、イベントモニターはあくまで内蔵の観察者である.イベントプロセッサhandlerとイベントモニターlistenerは同じことではありません.前者は、イベントを関連する関数に伝える手段であり、このようなモデルではイベントは一つのコールバック方法しか作成できないということを意味します.一方、モニタモードでは、一つのイベントはいくつかのモニターと関連付けられてもよい.各モニターは他のモニターと独立して変更できます.例えば、SanFrancico Chronicaleの新聞社にとって、その購読者jeはNew York Timesを決めていないに違いない.同じように、joeはLindsayも新聞を購読しているかどうかを気にしません.いずれも自分のデータと関連行為を処理します.
例えば、イベントモニターを使用して、同じイベントに複数の関数を応答させることができる.
つまり、モニターと観察者の間の共通点は明らかであり、彼らは互いに同義語である.彼らは特定のイベントを購読して、イベントの発生を待っています.イベントが発生すると、購読者のコールバック関数が通知されます.彼らに伝えられるパラメータはイベントの発生時間、イベントの種類、イベントの発祥地などの有用な情報を含んでいます.
観察者モードが適用される場合:
人間の行為とアプリケーションの行為を分離したいなら、観察者モードはこのような場合に適しています.利用者との操作を結びつけてブラウザから来たもの、例えばclick、keyliesなどの基本DOMイベントを実現しないほうがいいです.アニメの始まりだけを気にしたり、誤字を発見したりするプログラマーにとっては、それらのイベントは有益な情報を提供できません.
例えば、ナビゲーションのタブタブタブタブをクリックすると、より多くの情報を含むメニューが開きます.もちろん、このclickを直接モニターしてもいいですが、これはどの要素が待ち受けているのかを知る必要があります.そうすると、もう一つの弊害はあなたの実現がclick事件と直接つながっています.clickを傍受するより良い方法は、観察可能なonTabChangeオブジェクトを作成することです.また、特定のイベントが発生した場合は、観察者全員に通知します.メニューがマウスがラベルを指している時やタブがフォーカスしている時に開くように変更すれば、このオブジェクトはこのような変更を処理してくれます.
観察者モードは挙動に基づく大規模なアプリケーションを開発する有力な手段である.一回のブラウザセッション中に、アプリケーションでは断続的に数十回のイベントが発生する可能性があります.イベント登録モニターの回数を削減して、観察対象者にイベントモニターを使って、各種の行動を処理して、情報をdelegateに彼女のすべての予約者に依頼します.メモリの消費を低減し、性能を向上させる.このようにすると、同じ要素に新しいイベントモニターを延々と追加しなくてもいいです.
観察可能なオブジェクトを作成することは、負荷時間のオーバヘッドをもたらす.しかし,これは不活性負荷技術を用いて解消できる.具体的には、新規の観察対象の実装をイベント通知の送信に延期すると、予約者はイベントが作成されていないときに購読できます.アプリケーションの初期ロード時間も影響を受けません.
観察者モードには観察者と観察者の二つの役割が存在する.発表者と購読者と呼ばれることもあります.このようなモードはjavascriptの中にいくつかの異なる実現方法があります.以下ではその中のいくつかの実現方法を考察します.
パターンの実践:
javascriptには様々な方法があります.発表者-購読者モードを実現できます.これらの例を展示する前に、まず各種の役割の出演者(対象)とその行為(方法)が準備されていることを確認します.
var Publisher = new Observable;
var Subscriber = function (news) {
//news delivered directly to my proch;
}
Publisher.subscribeCustomer(Subscriber);
Publisher.deliver('extre,extre,read all about it!');
Publisher.unSubscribeCustomer(Subscriber);
このモデルでは,発表者が明らかに支配的であることが分かった.彼らはお客様の登録を担当しています.そして投函を停止する権利があります.最後に新しい新聞が出版されたらお客さんに届けます.上のコードは新しい観察対象を作成しました.3つの例の方法があります.subscribe Customer、unSubscribeCustomerとdeliver.subscribe Cusstomer法は,ある購読者のフィードバック関数をパラメータとする.deliverメソッドは、呼び出し中にこれらのコールバック関数によってデータを各購読者に送信します.
次の例は同じ問題を処理しますが、発表者と購読者の間のインタラクティブな方式は違います.
var newYorkTime = new Publisher;
var AustinHerald = new Publisher;
var SfChronicle = new Publisher;
var Jon = function (from) {
console.log('Delivery from'+from+'to jon');
}
var Lindsay = function (from) {
console.log('Delivery from'+from+'to Lindsay');
}
var Quadaras = function (from) {
console.log('Delivery from'+from+'to Quadaras');
}
jon.
subscribe(newYorkTime).
subscribe(SfChronicle);
Lindsay.
subscribe(newYorkTime).
subscribe(AustinHerald).
subscribe(SfChronicle);
Lindsay.
subscribe(newYorkTime).
subscribe(SfChronicle);
newYorkTime.deliver('Here is your paper!');
AustinHerald.deliver('News').deliver('REviews').deliver('Coupons');
SfChronicle.deliver('the weather is sill chilly').deliver('hello..');
この例では、発表者の作成方式と購読者がデータを受信する方式はあまり変わっていませんが、購読と購読権のための一方は購読者になりました.もちろん、データの送信を担当するのはまだ投稿者の方です.このクラスの発表者はピュアブルースターの例です.彼はdeliverの方法を持っています.予約者の関数としてはsubscribeとunsubscribeの2つの方法がある.予約者は普通のフィードバック関数です.この二つの方法はFunctionのprototypeを拡張することによって追加されました.次は必要なAPIを一歩ずつ構築します.
観察者APIを構築する:
function Publisher(){
this.subscribe = [];
}
すべてのPublisherの例はデータを送ることができるはずです.deliver方法をPublisherのprototypeに追加すれば、彼はすべてのPublisherの対象に共有されます.Publisher.prototype.deliver = function (data) {
this.subscribes.forEach(
function (fn) {
fn(data);
}
);
return this;
}
この方法はJavascript 1.6に新たに加えられた配列方法forEachを使用して、各購読者を一つ一つ処理します.forEach方法は「草の山」に対して最初から最後まで訪問して、針、針の索引と全体の配列を調整方法に提供します.購読者配列の各針は、Joe、Lindsay、Qudarasなどのコールバック関数である.deliver方法は、thisを戻り値として使用するので、この方法をチェーン式で呼び出すことができます.
次は購読者の購読能力を与えることです.
Function.prototype.subscribe = function (publisher) {
var _this = this;
var alreadyExists = publisher.subscribes.some(
function (el) {
return el===_this;
}
);
if (!alreadyExists) {
publisher.subscribes.push(this);
}
return this;
}
このコードはFunctionのprototypeです.Publisherオブジェクトをパラメータとするsubscribe方法を追加しました.すべての関数がこの方法を呼び出すことができます.subscribe法はまずthis変数を定義して、thisを与えます.配列として後で使用されるsome方法パラメータの匿名関数は、この変数にクローズド機構を介してアクセスし、subscribe法を呼び出すためのその関数オブジェクトにアクセスする.someもjavascript 1.6の中で新しく増加した配列方法で、それは一つのコールバック関数をパラメータとして、そして一つ一つ配列の各要素にアクセスして、それをパラメータとしてそのコールバック関数を呼び出します.少なくとも一回の呼び出し関数があればtrueに戻ります.some方法はtureに戻ります.そうでなければ、some方法はfalseに戻ります.subscribeは、someメソッドの戻り値をalreadyExistsに割り当て、この変数の値に基づいて指定された投稿者に購読者を追加するかどうかを決定する.最後にsubscribe方法はthisに戻り、チェーン呼び出しをサポートします.
unsubscribe方法は、イベントの投稿者の観察を停止するために、購読者のために使用できる.
Function.prototype.unsubscribe = function (publisher) {
var _this = this;
publisher.subscribes = publisher.subscribes.filter(
function (el) {
return el !== _this;
}
);
return this;
}
ある1回限りのイベントを傍受した後、リピーターの段階で直ちにイベントをキャンセルします.そのやり方は大体次の通りです.var publisherObject = new Publisher();
var observerObject = function (data) {
//process data
console.log(data);
//unsubscribe from this publisher
arguments.callee.unsubscribe(publisherObject);
}
observerObject.subscribe(publisherObject);
現実世界では、観察者モードは多くのjavascriptプログラマーが協力して開発した大型プログラムに特に役立つ.APIの柔軟性を向上させ、並列開発の複数の実装を互いに独立して修正することができる.開発者として、自分のアプリケーションの中で何が「興味のあるとき」なのかを決められます.あなたが監聴しているのは、click、load、blur、mouseoverなどのブラウザイベントではなく、リッチユーザーインターフェースアプリケーションの中で、drag、dropmoved、completteeとtabSwitchは興味深いイベントかもしれません.彼らはすべて普通のブラウザー事件の基礎の上で抽象的に出てくる観察可能な事件で、発表者の対象からその傍受者に放送することができます.インスタンスアニメーション:
アニメーションは、アプリケーションで観察できるオブジェクトを実現するための良いスタートラインです.まばたきの間に、少なくとも3つの観察できる瞬間を思いつくことができます.開始、終了、進行中です.この例では、私たちはそれぞれワンストップ、onComplette、onTweenと呼びます.以下のコードは前に作成したPublisherツールでこれらのイベントを実現する過程を示しています.
var Animation = function (o) {
this.onStart = new Publisher,
this.onComplete = new Publisher,
this.onTween = new Publisher;
}
Animation.method('fly', function () {
//begin animation
this.onStart.deliver();
for (...) { //loop through frames
//deliver frame number
this.onTween.deliver(i);
}
//end animation
this.onComplete.deliver();
});
//setup an account with the animation manager
var Superman = new Animation({config});
//Begin implementing subscribers
var putOnCape = function (i) {}
var takeOffCape = function (i) {}
putOnCape.subscribe(Superman.onStart);
takeOffCape.subscribe(Superman.onComplete);
//fly can be called anywhere
Superman.fly();
//for instance:
addEvent(element, 'click', function () {
Superman.fly();
});
スーパーマンにマントを羽織って和解のもとにマントを羽織る機能を果たしている人なら、このような働き方がいいと思います.発表者の助けを借りて、スーパーマンはいつ離陸しますか?またいつ地上に戻りますか?これらの時刻を予約するだけでいいです.DOMシナリオプログラミング環境における高レベルイベントモードでは、イベントモニターはあくまで内蔵の観察者である.イベントプロセッサhandlerとイベントモニターlistenerは同じことではありません.前者は、イベントを関連する関数に伝える手段であり、このようなモデルではイベントは一つのコールバック方法しか作成できないということを意味します.一方、モニタモードでは、一つのイベントはいくつかのモニターと関連付けられてもよい.各モニターは他のモニターと独立して変更できます.例えば、SanFrancico Chronicaleの新聞社にとって、その購読者jeはNew York Timesを決めていないに違いない.同じように、joeはLindsayも新聞を購読しているかどうかを気にしません.いずれも自分のデータと関連行為を処理します.
例えば、イベントモニターを使用して、同じイベントに複数の関数を応答させることができる.
var el = $('example');
var fn1 = function(e){}
var fn2 = function(e){}
addEvent(el,'click',fn1)
addEvent(el,'click',fn2)
しかし、イベントプロセッサはできません.var el = $('example');
var fn1 = function(e){}
var fn2 = function(e){}
el.onclick = fn1;
el.onclick = fn2;
第1の例では、イベントモニターが使用されるので、fn 1およびfn 2が起動される.第二の例では、第二のonclick割当値は第一回をカバーし、fn 2だけを呼び出します.つまり、モニターと観察者の間の共通点は明らかであり、彼らは互いに同義語である.彼らは特定のイベントを購読して、イベントの発生を待っています.イベントが発生すると、購読者のコールバック関数が通知されます.彼らに伝えられるパラメータはイベントの発生時間、イベントの種類、イベントの発祥地などの有用な情報を含んでいます.
観察者モードが適用される場合:
人間の行為とアプリケーションの行為を分離したいなら、観察者モードはこのような場合に適しています.利用者との操作を結びつけてブラウザから来たもの、例えばclick、keyliesなどの基本DOMイベントを実現しないほうがいいです.アニメの始まりだけを気にしたり、誤字を発見したりするプログラマーにとっては、それらのイベントは有益な情報を提供できません.
例えば、ナビゲーションのタブタブタブタブをクリックすると、より多くの情報を含むメニューが開きます.もちろん、このclickを直接モニターしてもいいですが、これはどの要素が待ち受けているのかを知る必要があります.そうすると、もう一つの弊害はあなたの実現がclick事件と直接つながっています.clickを傍受するより良い方法は、観察可能なonTabChangeオブジェクトを作成することです.また、特定のイベントが発生した場合は、観察者全員に通知します.メニューがマウスがラベルを指している時やタブがフォーカスしている時に開くように変更すれば、このオブジェクトはこのような変更を処理してくれます.
観察者モードは挙動に基づく大規模なアプリケーションを開発する有力な手段である.一回のブラウザセッション中に、アプリケーションでは断続的に数十回のイベントが発生する可能性があります.イベント登録モニターの回数を削減して、観察対象者にイベントモニターを使って、各種の行動を処理して、情報をdelegateに彼女のすべての予約者に依頼します.メモリの消費を低減し、性能を向上させる.このようにすると、同じ要素に新しいイベントモニターを延々と追加しなくてもいいです.
観察可能なオブジェクトを作成することは、負荷時間のオーバヘッドをもたらす.しかし,これは不活性負荷技術を用いて解消できる.具体的には、新規の観察対象の実装をイベント通知の送信に延期すると、予約者はイベントが作成されていないときに購読できます.アプリケーションの初期ロード時間も影響を受けません.