什么是发布订阅模式
发布订阅模式又叫观察者模式,定义的是对象间一对多的依赖关系。当对象A的状态发生改变时,所有依赖于对象A的其他对象都会收到通知,并触发他们各自的回调函数。其中,对象A就是发布者,其他对象就是订阅者,类似于A像其他对象推送消息。JS中的事件机制就是发布订阅者模式的体现。
发布订阅模式的特点
优点:(1)时间上的解耦
(2)对象上的解耦
缺点:(1)创建订阅者要消耗时间和内存,就算订阅的消息一直不发生,订阅者也会一直存在于内存中;
(2)过渡使用会导致对象之间的关系过于弱化,程序难以跟踪维护。
发布订阅模式的实现步骤
(1)指定一个充当发布者的对象,可以是某个详细的对象,也可以是全局对象(作为中间代理)
(2)给发布者添加缓存列表,用于存放回调函数,以便通知订阅者。
(3)发布消息时,会遍历缓存列表中对应key值得数组,触发里面的回调函数的执行。
通用发布订阅模式
/**发布订阅模式的通用实现 */
//将发布订阅功能单独提出来,放在一个对象内
var event = {
clientList: {},
listen: function(key,fn){
if(!this.clientList[key]){
this.clientList[key] = [];
}
this.clientList[key].push(fn);
},
trigger: function(){
var argus = Array.prototype.slice.call(arguments,0),
key = argus[0],
fns = this.clientList[key];
if(!fns || fns.length==0){
return false;
}
for(var i=0;i=0;j--){
if(fn === fns[j]){
fns.splice(j,1);
}
}
}
}
}
//给对象安装发布订阅功能的函数
var installEvent = function(obj){
for(var i in event){
obj[i] = event[i];
}
}
var saleOffice = {};
installEvent(saleOffice);
//测试
saleOffice.listen('square88',fn1 = function(price){
console.log('价格为:'+ price);
})//小明的订阅
saleOffice.listen('square110',fn2 = function(price){
console.log("price="+ price);
})//小红的订阅
saleOffice.listen('square88',fn3 = function(price){
console.log('面积为:'+ '88');
})
saleOffice.trigger('square88',1000000);
saleOffice.trigger('square110',3000000);
saleOffice.remove('square110',fn2);
saleOffice.trigger('square110',3000000);
全局发布订阅模式
/**全局发布订阅对象 */
// 避免不断的创建发布对象和缓存列表,节约空间;形成一个中介,发布者和订阅者之间解耦
var Event = (function(){
var clientList = {},
listen,
trigger,
remove;
listen = function(key,fn){
if(!clientList[key]){
clientList[key] = [];
}
clientList[key].push(fn);
};
trigger = function(){
var argu = Array.prototype.slice.call(arguments,0),
key = argu[0];
fns = clientList[key];
if(!fns || fns.length == 0){
return false;
}
for(var i=0;i=0;j--){
if(fn===fns[j]){
fns.splice(j,1);
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
})()
//测试
Event.listen('square88',fn1 = function(price){
console.log('价格为:'+ price);
})//小明的订阅
Event.listen('square110',fn2 = function(price){
console.log("price="+ price);
})//小红的订阅
Event.listen('square88',fn3 = function(price){
console.log('面积为:'+ '88');
})
Event.trigger('square88',1000000);
Event.trigger('square110',3000000);
Event.remove('square110',fn2);
Event.trigger('square110',3000000);
全局发布订阅者模式(1)节约资源;避免为每个对象添加listen,trigger方法,以及缓存列表;(2)解除了耦合;由之前的通用发布订阅模式可以知道,订阅者需要知道发布对象的名字才能订阅事件;通过一个全局的中介,我们无需关心谁是发布者,谁是订阅者,这样有利于完成模块间的通信。