一、观察者模式
javascript中所有的事件应用了此模式,此模式大大降低对象间的耦合,并且易于扩展。简单来说,其实现思路就是函数回调,由订阅者提供对应事件的处理函数,当发布者发布消息,就会调用事件处理队列中的函数。静态语言,用接口来实现不同事件和不同处理函数的对应。javascript动态语言直接用hash表,和函数传递。
实现:
var publisher = {
listeners:{
'any':[]//事件类型:订阅者
},
//注册
addListener:function(fn,type){
type = type || 'any';
if(typeof this.listeners[type] === 'undefined'){
this.listeners[type] = [];
}
this.listeners[type].push(fn);
},
//取消注册
remove:function(type,fn){
this.visitlisteners('remove',fn,type);
},
//发布信息
publish:function(publication,type){
this.visitlisteners('publish',publication,type);
},
//遍历某事件的订阅者
visitlisteners:function(action,arg,type){
var pubtype = type || 'any',
listeners = this.listeners[pubtype],
i,
max = listeners.length;
for (i=0;i<max;i++) {
if(action === 'publish'){
//执行订阅者方法
listeners[i](arg);
}else{
//取消订阅
if(listeners[i] === arg){
listeners.splice(i,1);
}
}
}
}
}
function makePublisher(o){
var i;
for(i in publisher){
if(publisher.hasOwnProperty(i) && typeof publisher[i] === 'function'){
o[i] = publisher[i];
}
}
o.listeners = {any:[]};
}
//测试
//发布者
var paper = {
daily:function(){
this.publish('aaaaaaaaaaaaaaa');
},
monthly:function(){
this.publish('bbbbbbbbbbbbbbb','monthly');
}
}
makePublisher(paper);
//订阅者
var joe = {
drinkCoffee:function(paper){
console.log('just read '+ paper);
},
sundayPreNap: function(monthly){
console.log('ablout to fall asleep read ' +monthly);
}
}
//注册
paper.addListener(joe.drinkCoffee);
paper.addListener(joe.sundayPreNap,'monthly');
//发布信息
paper.daily();//just read aaaaaaaaaaaaaaa 结果
paper.daily();//just read aaaaaaaaaaaaaaa
paper.daily();//just read aaaaaaaaaaaaaaa
paper.monthly();//ablout to fall asleep read
1.有一个'any'的事件类型,用于处理没有对应事件名字的事件函数。
2.此实现可以将任意对象变成发布者,利用makePublisher()函数。