feb 23, 2015
觀察者模式又叫發布訂閱模式(publish/subscribe),它定義了一種一對多的關係,讓多個觀察者物件同時監聽某乙個主題物件,這個主題物件的狀態發生變化時就會通知所有的觀察者物件,使得它們能夠自動更新自己。
使用觀察者模式的好處:
支援簡單的廣播通訊,自動通知所有已經訂閱過的物件。
頁面載入後目標物件很容易與觀察者存在一種動態關聯,增加了靈活性。
目標物件與觀察者之間的抽象耦合關係能夠單獨擴充套件以及重用。
js 裡對觀察者模式的實現是通過**來實現的,我們來先定義乙個 pubsub 物件,其內部包含了 3 個方法:訂閱、退訂、發布。
var pubsub = {};
(function (q) , // **函式存放的陣列
subuid = -1;
// 發布方法
q.publish = function (topic, args)
settimeout(function ()
}, 0);
return true;
};//訂閱方法
q.subscribe = function (topic, func)
var token = (++subuid).tostring();
topics[topic].push();
return token;
};//退訂方法
q.unsubscribe = function (token) }}
}return false;
};} (pubsub));
使用方式如下:
//來,訂閱乙個
pubsub.subscribe('example1', function (topics, data) );
//發布通知
pubsub.publish('example1', 'hello world!');
pubsub.publish('example1', ['test', 'a', 'b', 'c']);
pubsub.publish('example1', [, ]);
怎麼樣?用起來是不是很爽?但是這種方式有個問題,就是沒辦法退訂訂閱,要退訂的話必須指定退訂的名稱,所以我們再來乙個版本:
//將訂閱賦值給乙個變數,以便退訂
var testsubscription = pubsub.subscribe('example1', function (topics, data) );
//發布通知
pubsub.publish('example1', 'hello world!');
pubsub.publish('example1', ['test', 'a', 'b', 'c']);
pubsub.publish('example1', [, ]);
//退訂
settimeout(function () , 0);
//再發布一次,驗證一下是否還能夠輸出資訊
pubsub.publish('example1', 'hello again! (this will fail)');
我們也可以利用原型的特性實現乙個觀察者模式,**如下:
function observer()
observer.prototype = ,
unsubscribe: function (fn) });
},update: function (o, thisobj) );}
};//測試
var o = new observer;
var f1 = function (data) ;
var f2 = function (data) ;
o.subscribe(f1);
o.subscribe(f2);
o.update("tom回來了!")
//退訂f1
o.unsubscribe(f1);
//再來驗證
o.update("tom回來了!");
如果提示找不到 filter 或者 foreach 函式,可能是因為你的瀏覽器還不夠新,暫時不支援新標準的函式,你可以使用如下方式自己定義:
if (!array.prototype.foreach) };}
if (!array.prototype.filter)
a.push(this[i]);
}return a;};}
如果想讓多個物件都具有觀察者發布訂閱的功能,我們可以定義乙個通用的函式,然後將該函式的功能應用到需要觀察者功能的物件上,**如下:
//通用**
var observer = ,
//退訂
removesubscriber: function (callback) }},
//發布
publish: function (what) }},
// 將物件o具有觀察者功能
make: function (o) }};
然後訂閱 2 個物件 blogger 和 user,使用 observer.make 方法將這 2 個物件具有觀察者功能,**如下:
var blogger =
};var user =
};observer.make(blogger);
observer.make(user);
使用方法就比較簡單了,訂閱不同的**函式,以便可以註冊到不同的觀察者物件裡(也可以同時註冊到多個觀察者物件裡):
var tom =
};var mm =
};// 訂閱
blogger.addsubscriber(tom.read);
blogger.addsubscriber(mm.show);
blogger.recommend(123); //呼叫發布\
//退訂
blogger.removesubscriber(mm.show);
blogger.recommend(456); //呼叫發布
//另外乙個物件的訂閱
user.addsubscriber(mm.show);
user.vote(789); //呼叫發布
根據 jquery1.7 版新增的 on/off 功能,我們也可以定義 jquery 版的觀察者:
(function ($) );
$.subscribe = function () ;
$.unsubscribe = function () ;
$.publish = function () ;
} (jquery));
呼叫方法比上面 3 個版本都簡單:
//**函式
function handle(e, 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) );
$.publish("/some/topic", ["a", "b", "c"]); // 輸出abc
//退訂(退訂使用的是/some/topic名稱,而不是**函式哦,和版本一的例子不一樣
$.unsubscribe("/some/topic");
可以看到,他的訂閱和退訂使用的是字串名稱,而不是**函式名稱,所以即便傳入的是匿名函式,我們也是可以退訂的。
觀察者的使用場合就是:當乙個物件的改變需要同時改變其它物件,並且它不知道具體有多少物件需要改變的時候,就應該考慮使用觀察者模式。
總的來說,觀察者模式所做的工作就是在解耦,讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響到另一邊的變化。
設計模式之觀察者模式
首先說了乙個自己的小例子吧,前兩天我的乙個朋友來找我玩,因為路途比較遠,我需要知道他的位置,然後安排好時間去接他,那麼在這個例子中,我就是乙個觀察者,需要時時刻刻觀察他的位置,我的朋友就是乙個被觀察者。那麼需要知道我朋友的位置,就有兩種方式,第一,我自己打 問,第二,我的朋友告訴我,下面我們來看看這...
設計模式之觀察者模式
一 作用 讓多個觀察者監視某一物件的變化,如果物件變化,則通知所有觀察者。二 例子 抽象主題類 public abstract class subject 移除觀察者 public void detach observer observer 向觀察者 們 發出通知 public void notif...
設計模式之觀察者模式
觀察者模式的定義是 定義物件間的一種一對多的依賴關係。當乙個物件的狀態發生變化時,所有依賴它的物件都會得到通知並自動更新 報社跟讀者的例子 我們用報社和讀者之間的關係來模擬觀察者模式。包含以下主體 報社 news office 讀者介面 reader 具體讀者 reader 二逼青年 reader ...