发布-订阅模式中存在三种角色,发布者、订阅者,二者彼此不知道对方的存在,需要通过第三者,即消息队列来建立联系。这和观察者模式是不同的。
发布订阅模式的优势在于,可以让两个对象松耦合地联系在一起,虽然不清楚彼此的细节,但这不影响它们之间相互通信。当有新的订阅者出现时,发布者的代码不需要任何修改; 同样发布者需要改变时,也不会影响到之前的订阅者。只要之前约定的事件名没有变化,就可以自由地改变它们。
不过如果使用过度,会导致程序难以跟踪维护和理解,调试bug不是件轻松的事情。
JS实现
function EventTarget(){
this.eventList = {}
}
EventTarget.prototype.add = function(type, fn){
if(typeof this.eventList[type] === 'undefined'){
this.eventList[type] = []
}
this.eventList[type].push(fn)
}
EventTarget.prototype.fire = function(){
var type = Array.prototype.shift.call(arguments), //取出第一个参数,事件名称。会修改arguments类数组本身
args = Array.prototype.slice.call(arguments)//把剩下的参数转换成数组
var task = this.eventList[type]
if(Array.isArray(task)){
for(var i=0; i <task.length; i++){
task[i](args)
}
}
}
EventTarget.prototype.remove = function(type, fn){
var task = this.eventList[type]
if(Array.isArray(task)){
for(var i=0; i<task.length; i++){
if(task[i] === fn){
task.splice(i, 1)
break
}
}
}
}
测试
var target = new EventTarget()
function readyCallback1(args){
console.log('is readyCallback1', args)
}
function readyCallback2(args){
console.log('is readyCallback2',args)
}
target.add('ready', readyCallback1)
target.add('ready', readyCallback2)
target.fire('ready', 'params1', 'params2')//可以传多个参数
setTimeout(function(){
console.log('----------')
target.remove('ready', readyCallback1)
target.fire('ready', 'params1')
}, 2000)
输出结果
is readyCallback1 [ 'params1', 'params2' ]
is readyCallback2 [ 'params1', 'params2' ]
----------
is readyCallback2 [ 'params1' ]
网友评论