一、适用场景
观察者模式,适用于有多个模块存在的,并且模块之间存在相互依赖或者相互通信的情况。使用观察者模式,可以降低耦合度,便于后期程序的扩展和维护。
二、实现原理
观察者模式是怎样做到模块间松散耦合,并且又不影响相互协作的呢?答案就是“观察者(observer)”。在JavaScript中,观察者是一个对象,该对象暴露3个函数给外部,分别是 publish() 、subscribe() 、unsubscribe(),它们分别用于推送通知、订阅消息、撤销订阅。模块之间通过观察者进行通信,而不直接与其他模块关联。具体流程如下:
假定有两个模块A和B,A是一个异步模块,负责从后台获取数据,B是另一个模块,负责展示数据到页面。观察者模式下,它们这样协作:
(1)模块B通过调用观察者(observer)的subscribe() 方法,订阅模块A的消息。就像模块B对观察者说:“Hey, man,如果模块A有什么消息,请马上告诉我。”
(2)模块A在获取到后台数据后,调用观察者(observer)的publish()方法,告诉observer:“Hey, buddy,我拿到数据了。”
(3)观察者(observer)收到消息后,告诉模块B:“模块A那家伙刚刚跟我说它拿到数据了,数据是什么什么balabala……”
(4)模块B拿到观察者(observer)给的数据后,做自己该做的事情。
三、代码分享
下面是一个观察者(observer)的代码:
var observer = (function(){
var events = {};
return {
//定义 subscribe() 方法,用于订阅某个事件名称,当订阅的事件发生时,调用相应的回调函数
subscribe: function (eventName,callback) {
if(!events.hasOwnProperty(eventName)){
events[eventName] = [];
}
events[eventName].push(callback);
},
//定义 unsubscribe() 方法,用于取消订阅,移除一个给定的函数
unsubscribe: function(eventName,callback){
var index = 0;
var len = 0;
if(events.hasOwnProperty(eventName)){
len = events[eventName].length;
for(;index < len;index++){
if(events[eventName][index] === callback){
events[eventName].splice(index,1);
break;
}
}
}
},
//定义 publish() 方法,用于发布消息(eventName),发布后,对应的回调函数将全部执行
//调用这个 publish() 方法时,传入的第一个参数必须是事件名称(eventName),后面可传入任意数量的参数
publish: function(eventName){
//除了第一个参数(即事件名称)外,将调用 publish() 函数的其他所有参数保存为一个数组
var data = Array.prototype.slice.call(arguments,1);
var index = 0;
var len = 0;
if(events.hasOwnProperty(eventName)){
len = events[eventName].length;
for(;index < len;index++){
events[eventName][index].apply(this,data);
}
}
}
};
})();
self.observer = observer;
下面是一个使用观察者的例子:
//假设这是模块A,向后台请求数据
$.ajax({
url: "test.action",
data:{},
success: function(r){
//请求成功后,调用观察者的publish() 方法
observer.publish('queryData',r);
}
});
上面的代码不会发生任何事情,直到模块B订阅了“queryData”消息。如下:
var showData = function(type,r){
var content = "";
if(r.result){
content = r.result;
}
else{
content = "No Data!"
}
$('#text').val(content);
}
observer.subscribe('queryData',showData );
1万+

被折叠的 条评论
为什么被折叠?



