Observer パターンは、Observer パターンとも呼ばれ、GoF が提案する 23 のソフトウェア設計パターンの 1 つです。 Observer パターンは、オブジェクトの状態が変化したときに、関連する他のオブジェクトに自動的に通知し、オブジェクトの状態を自動的に更新する機能です。
Observer パターンの概念
オブザーバー モードは動作モードの 1 つであり、その機能は、オブジェクトの状態が変化したときに、関連付けられている他のオブジェクトに自動的に通知し、オブジェクトの状態を自動的に更新することです。
Observer パターンは、オブジェクトとそれに依存する他のオブジェクトの間の状態の同期を維持するために、関連付けられたオブジェクトに同期通信の手段を提供します。
オブザーバーモードの役割:
被験者 (観測対象)
観察されているオブジェクト。監視する必要がある状態が変化した場合、キュー内のすべてのオブザーバー オブジェクトに通知する必要があります。サブジェクトは、オブザーバー オブジェクトのキュー リストを維持 (追加、削除、通知) する必要があります。
具体的な件名
観察された人物の具体的な実現。いくつかの基本的な属性の状態とその他の操作が含まれています。
観察者
インターフェイスまたは抽象クラス。 Subject の状態が変化すると、Observer オブジェクトはコールバック関数を通じて通知されます。
コンクリートオブザーバー
オブザーバーの具体的な実装。通知後、特定のビジネス ロジックの処理が完了します。
オブザーバー パターン (パブリッシャー/サブスクライバー パターンとも呼ばれます) は、私たちが普段使用する dom イベントを含め、最も一般的に使用されているパターンの 1 つです。と dom オブザーバー パターン。
div.onclick = function click (){ alert ( ”click' ) }
div のクリック イベントをサブスクライブしている限り、div がクリックされると、関数のクリックがトリガーされます。
それでは、観察者のパターンとは何でしょうか? まず、人生における観察者のパターンを見てみましょう。
ハリウッドには「電話しないでください、私が電話します。」という有名な言葉があります。この文は観察者パターンの詳細を説明しています。 ここで、「私」は発行者、「あなた」は購読者です。
別の例として、私が面接のためにその会社に来たとき、面接後にどの面接官も私にこう言いました。「連絡先を残してください。何かニュースがあればお知らせします。」 ここで「私」は購読者であり、インタビュアーは発行者です。したがって、面接の結果について毎日または毎時間尋ねる必要はありません。コミュニケーションの主導権は面接官にあります。そして、連絡先情報を提供する必要があるだけです。
オブザーバー パターンは、2 つのモジュール間の分離を適切に実現できます。 チームで HTML5 ゲームを開発しているとします。ゲームの開始時に、いくつかの画像素材を読み込む必要があります。これらの画像をロードした後、ゲーム ロジックが実行されます。これは複数人の協力が必要なプロジェクトであるとします。私が Gamer モジュールと Map モジュールを完成させ、同僚 A が画像ローダーのloadImage を作成したとします。
loadImage のコードは次のとおりです
loadImage( imgAry, function(){ Map.init(); Gamer.init(); } )
画像がロードされた後、マップがレンダリングされ、ゲーム ロジックが実行されます。このプログラムは、ある日突然、ゲームにサウンド機能を追加する必要があることを思い出しました。画像ローダーへのコード。
loadImage( imgAry, function(){ Map.init(); Gamer.init(); Sount.init(); } )
しかし、このモジュールを書いた同僚 A が海外旅行に行ったので、こんにちは、loadImage 関数はどこにありますか? 変更後の影響はありますか?不安なことが起こりました。
のように書くことができたらどうでしょうか。loadImage.listen( ”ready', function(){ Map.init(); }) loadImage.listen( ”ready', function(){ Gamer.init(); }) loadImage.listen( ”ready', function(){ Sount.init(); })
loadImage が完了したら、その作業は完了しているため、その後何が起こるかは気にしません。次に必要なのはシグナルを発行することだけです。
loadImage.trigger( ”ready' );
その後、loadImage の「ready」イベントをリッスンするオブジェクトに通知が行われます。面接者は、面接結果を受け取った後にどこに食事に行くかについてはまったく気にしません。面接の実施のため、候補者の履歴書を集めてください。面接の結果が出たら、履歴書に記載されている電話番号に従って個別に通知されます。
非常に多くの概念について話した後、具体的な実装を説明しましょう。実装プロセスは実際には非常に簡単です。面接官は履歴書を箱に入れ、面接官に 1 人ずつ電話をかけます。結果を知らせるのに最適な時期です
Events = function() { var listen, log, obj, one, remove, trigger, __this; obj = {}; __this = this; listen = function( key, eventfn ) { //把简历扔盒子, key就是联系方式. var stack, _ref; //stack是盒子 stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = []; return stack.push( eventfn ); }; one = function( key, eventfn ) { remove( key ); return listen( key, eventfn ); }; remove = function( key ) { var _ref; return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0; }; trigger = function() { //面试官打电话通知面试者 var fn, stack, _i, _len, _ref, key; key = Array.prototype.shift.call( arguments ); stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = []; for ( _i = 0, _len = stack.length; _i < _len; _i++ ) { fn = stack[ _i ]; if ( fn.apply( __this, arguments ) === false) { return false; } } return { listen: listen, one: one, remove: remove, trigger: trigger } }
//订阅者 var adultTv = Event(); adultTv .listen( ”play', function( data ){ alert ( “今天是谁的电影” + data.name ); }); //发布者 adultTv .trigger( ”play', { ‘name': ‘麻生希' } )