您的位置:首页 > Web前端 > JavaScript

轻松掌握:JavaScript观察者模式

2016-08-26 00:48 531 查看

观察者模式

观察者模式也叫“订阅者/发布者”模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息。

观察者模式被广泛地应用于JavaScript客户端编程中。所有的浏览器事件(mouseover,keypress等)都是使用观察者模式的例子。

使用这个模式的最主要目的就是促进对象之间的解耦(弱化对象之间的联系)。在观察者模式中,一组对象订阅另一个对象的指定活动并得到通知。

如:

document.body.addEventListener('click',function(){
alert(2);
},false);

以上代码订阅了document.body的click事件,当body被点击时,body便会向订阅者发布消息;

实现观察者模式的一般步骤:

先指定谁充当发布者;

给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;

发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数;还可在回调函数内加入一些参数;

(也可先发布消息,将消息保存起来,当有订阅者时就将该消息重新发布给他)

发布-订阅模式的通用实现:
var Publisher = (function(){
//listenerList用来保存一系列的key,每个key为保存了所有订阅者函数fn的数组{ keyA:[fn1,fn2...], keyB:[...]...}
//类似:可以为同一事件注册多个回调函数
var listenerList = {};
return {
addListener: function(key,fn){
if(!listenerList[key]){
listenerList[key] = [];
}
if(listenerList[key].indexOf(fn) === -1){ //检测fn是否已订阅,注意indexOf方法不支持IE9以下,可用for循环代替
listenerList[key].push(fn);
}
},
publish: function(){
var key = Array.prototype.shift.call(arguments),
fns = listenerList[key];
if(!fns||fns.length === 0){
return false;
}
for(var i = 0,fn;fn = fns[i++];){
fn.apply(this,arguments);
}
},
removeListener: function(key,fn){
var fns = listenerList[key];
if(!fns){
return false;
}
if(!fn){ //若没指定fn,则表示取消所有订阅
fns && (fns.length = 0);
}else{  //可直接用fns.splice(listenerList[key].indexOf(fn),1);但indexOf方法不支持IE9以下
for(var l = fns.length - 1; l >=  0; l--){
if(fns[l] === fn){
fns.splice(l,1);
}
}
}
}
};
})();

Publisher.addListener('month',function(num){  //订阅month
console.log('本月数量: '+num);
});
Publisher.addListener('month',function(price){
console.log('本月价格: '+price);
});
Publisher.addListener('week',function(num){
console.log('本周数量: '+num);
});
Publisher.publish('month',123);  //手动发布消息
//本月数量: 123
//本月价格: 123
Publisher.publish('week',5);
//本周数量: 5

实际应用:

$.ajax('http://xxx.com?login',function(data){
Publisher.publish('loginSuccess',data);  //若登录成功则向所有订阅者发布登录成功的消息
});
//以下在各个模块添加订阅消息
var header = (function () {
Publisher.addListener('loginSuccess', function (data) {
header.setAvatar(data.avatar);
});
return {
setAvatar: function (data) {
console.log('设置header模块的头像')
}
}
})();
var nav = (function () {
Publisher.addListener('loginSuccess', function (data) {
nav.setAvatar(data.avatar);
});
return {
setAvatar: function (avatar) {
console.log('设置header模块的头像')
}
}
})();
//...可随意添加其他模块

参考文献:

《JavaScript模式》

《JavaScript设计模式与开发实践》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: