導入
オブザーバーモードは、パブリッシュ/サブスクライブとも呼ばれます。 1対多数の関係を定義し、複数のオブザーバーオブジェクトがトピックオブジェクトを同時に聞くことができます。このトピックオブジェクトの状態が変更されると、すべてのオブザーバーオブジェクトに通知されるため、自動的に更新できます。
オブザーバーモードを使用することの利点:
1.単純なブロードキャスト通信をサポートし、サブスクライブされたすべてのオブジェクトに自動的に通知します。
2。ページが読み込まれた後、ターゲットオブジェクトはオブザーバーとの動的相関を簡単に行うことができ、柔軟性が向上します。
3.ターゲットオブジェクトとオブザーバーの抽象カップリング関係は、個別に拡張および再利用できます。
テキスト(バージョン1)
JSでのオブザーバーパターンの実装は、コールバックを通じて達成されます。最初に、サブスクリプション、登録解除、公開の3つの方法を含むpubSubオブジェクトを定義しましょう。
コードコピーは次のとおりです。
var pubsub = {};
(function(q){
var topics = {}、//コールバック関数によって保存されている配列
subuid = -1;
//公開方法
Q.publish = function(topic、args){
if(!topics [topic]){
falseを返します。
}
setimeout(function(){
var subscribers = Topics [トピック]、
len =購読者? subscribers.length:0;
while(len-){
加入者[len] .func(topic、args);
}
}、0);
trueを返します。
};
//サブスクライブメソッド
q.subscribe = function(topic、func){
if(!topics [topic]){
トピック[トピック] = [];
}
var token =(++ subuid).toString();
トピック[トピック] .push({
トークン:トークン、
FUNC:FUNC
});
トークンを返します。
};
// unsubscriptionメソッド
Q.Unsubscribe = function(token){
for(トピックのvar m){
if(Topics [M]){
for(var i = 0、j = topics [m] .length; i <j; i ++){
if(Topics [m] [i] .token === token){
トピック[M] .splice(i、1);
トークンを返します。
}
}
}
}
falseを返します。
};
}(pubsub));
それを使用する方法は次のとおりです。
コードコピーは次のとおりです。
//来て、1つを購読してください
pubsub.subscribe( 'embles1'、function(Topics、data){
console.log(topics + ":" + data);
});
//リリースの通知
pubsub.publish( 'Example1'、 'Hello World!');
pubsub.publish( 'emple1'、['test'、 'a'、 'b'、 'c']);
pubsub.publish( 'example1'、[{'color': 'blue'}、{'text': 'hello'}]);
それはどうですか?使用するのはとても良いことではありませんか?しかし、この方法には問題があります。つまり、登録解除する方法はありません。登録を解除したい場合は、登録解除の名前を指定する必要があるため、別のバージョンにアクセスしましょう。
コードコピーは次のとおりです。
//サブスクライブにサブスクリプションを割り当てて、登録解除します
var testsubscription = pubsub.subscribe( 'emple1'、function(topics、data){
console.log(topics + ":" + data);
});
//リリースの通知
pubsub.publish( 'Example1'、 'Hello World!');
pubsub.publish( 'emple1'、['test'、 'a'、 'b'、 'c']);
pubsub.publish( 'example1'、[{'color': 'blue'}、{'text': 'hello'}]);
// unsubscription
setimeout(function(){
pubsub.unsubscribe(testsubscription);
}、0);
//もう一度公開して、情報を出力できるかどうかを確認する
pubsub.publish( 'example1'、 'hello gar!(これは失敗する)');
バージョン2
プロトタイプの特性を使用してオブザーバーパターンを実装することもできます。コードは次のとおりです。
コードコピーは次のとおりです。
function overserver(){
this.fns = [];
}
Observer.prototype = {
購読:function(fn){
this.fns.push(fn);
}、
登録解除:function(fn){
this.fns = this.fns.filter(
関数(el){
if(el!== fn){
Elを返します。
}
}
);
}、
更新:function(o、thisobj){
var scope = thisobj ||ウィンドウ;
this.fns.foreach(
関数(el){
el.call(scope、o);
}
);
}
};
//テスト
var o = new Observer;
var f1 = function(data){
console.log( 'robbin:' + data + '、迅速に動作!');
};
var f2 = function(data){
console.log( 'randall:' + data + '、余分な給与を得るために彼を見つけてください!');
};
o.Subscribe(f1);
o.Subscribe(f2);
o.update(「トムは戻ってきた!」)
// F1に登録解除します
o.Unsubscribe(f1);
//もう一度確認してください
o.update( "Tom Is Back!");
フィルターまたはforeach機能が見つからない場合、ブラウザが十分に新しくなく、当面の間新しい標準機能をサポートしていないためかもしれません。次の方法で自分で定義できます。
コードコピーは次のとおりです。
if(!array.prototype.foreach){
array.prototype.foreach = function(fn、thisobj){
var scope = thisobj ||ウィンドウ;
for(var i = 0、j = this.length; i <j; ++ i){
fn.call(scope、this [i]、i、this);
}
};
}
if(!array.prototype.filter){
array.prototype.filter = function(fn、thisobj){
var scope = thisobj ||ウィンドウ;
var a = [];
for(var i = 0、j = this.length; i <j; ++ i){
if(!fn.call(scope、this [i]、i、this)){
続く;
}
a.push(this [i]);
}
aを返します。
};
}
バージョン3
複数のオブジェクトがオブザーバー公開サブスクリプションの関数を持たせる場合、共通の関数を定義し、オブザーバー関数を必要とするオブジェクトに関数の関数を適用できます。コードは次のとおりです。
コードコピーは次のとおりです。
//ユニバーサルコード
var Observer = {
//サブスクリプション
addsubscriber:function(callback){
this.subscribers [this.subscribers.length] = callback;
}、
// unsubscription
removesubscriber:function(callback){
for(var i = 0; i <this.subscribers.length; i ++){
if(this.subscribers [i] === callback){
削除(this.subscribers [i]);
}
}
}、
//リリース
パブリッシュ:function(what){
for(var i = 0; i <this.subscribers.length; i ++){
if(typeof this.subscribers [i] === 'function'){
this.subscribers [i](what);
}
}
}、
//オブジェクトを作成しますoオブザーバー関数を持っています
make:function(o){
for(これでvar i){
o [i] = this [i];
o.subscribers = [];
}
}
};
次に、2つのオブジェクトブロガーとユーザーを購読し、Observer.Meathを使用してこれらの2つのオブジェクトにObserver機能を持つようにします。コードは次のとおりです。
コードコピーは次のとおりです。
var blogger = {
お勧め:function(id){
var msg = 'dudu推奨投稿:' + id;
this.publish(msg);
}
};
var user = {
投票:function(id){
var msg = '誰かが投票した!id =' + id;
this.publish(msg);
}
};
Observer.make(blogger);
Observer.make(user);
使用方法は比較的簡単です。さまざまなコールバック関数を購読して、さまざまなオブザーバーオブジェクトに登録できるようにします(または複数のオブザーバーオブジェクトを同時に登録できます):
コードコピーは次のとおりです。
var tom = {
読む:function(what){
console.log( 'トムは次のメッセージを見ました:' +何)
}
};
var mm = {
show:function(what){
console.log( 'mmは次のメッセージを見ました:' +何)
}
};
// 購読する
blogger.addsubscriber(tom.read);
blogger.addsubscriber(mm.show);
blogger.recommend(123); //公開を呼び出します
// unsubscription
blogger.removesubscriber(mm.show);
blogger.recommend(456); //公開を呼び出します
//別のオブジェクトを購読します
user.addsubscriber(mm.show);
user.vote(789); //公開を呼び出します
jQueryバージョン
jQueryバージョン1.7に追加されたオン/オフ関数によると、jQueryバージョンのオブザーバーを定義することもできます。
コードコピーは次のとおりです。
(function($){
var o = $({});
$ .subscribe = function(){
O.on.Apply(o、arguments);
};
$ .unsubscribe = function(){
o.off.Apply(o、arguments);
};
$ .publish = function(){
o.trigger.apply(o、arguments);
};
}(jQuery));
呼び出し方法は、上記の3つのバージョンよりも簡単です。
コードコピーは次のとおりです。
//コールバック関数
関数ハンドル(e、a、b、c){
// `e`はイベントオブジェクトであり、注意は必要ありません
console.log(a + b + c);
};
//サブスクリプション
$ .subscribe( "/some/topic"、handle);
//リリース
$ .publish( "/some/topic"、["a"、 "b"、 "c"]); //出力ABC
$ .unsubscribe( "/some/topic"、handle); //サブスクライブを解除します
//サブスクリプション
$ .subscribe( "/some/topic"、function(e、a、b、c){
console.log(a + b + c);
});
$ .publish( "/some/topic"、["a"、 "b"、 "c"]); //出力ABC
// unsubscribe(unsubscribeは/some/topic名を使用します。コールバック関数ではなく、バージョン1の例とは異なります
$ .unsubscribe( "/some/topic");
コールバック関数名ではなく、そのサブスクリプションとサブスクライブの文字列名があることがわかります。したがって、着信匿名関数が渡されても、登録解除できます。
要約します
オブザーバーの使用は次のとおりです。オブジェクトが他のオブジェクトを同時に変更して変更し、変更する必要があるオブジェクトの数がわからない場合、オブザーバーモードの使用を検討する必要があります。
全体として、オブザーバーのパターンが行うことは分離することであり、結合の両側にコンクリートではなく抽象化に依存するようにします。これにより、互いの変化が反対側の変化に影響を与えないことが可能になります。