javascript设计模式学习之八_发布订阅(观察者)模式
一、发布订阅模式定义
jQuery中的callbacks,defered,promise本质上就是发布订阅模式的实现。ES6的promise内部实现未开源,不了解具体机制
发布订阅模式又叫做观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
发布—订阅模式的优点十分明显,一是可以实现时间上的解耦,二是可以实现对象之间的解耦。
发布—订阅模式的缺点也很明显,订阅者订阅一个消息后,如果该消息最后都没有发生,这个订阅者依旧会存在于内存中。
javascript中的事件机制就属于发布订阅模式的一种。
如document.body.addEventListener(),这里document.body就是事件的发布者,addEventListener就是事件发布者提供的一个订阅事件的接口方法,所有其他对象都可以调用这个方法来订阅document.body上发生的对应事件,并自定义自己的事件处理方法。
一般的发布订阅者模式中,发布者还会提供一个trigger方法,用于发布消息。
二、java中观察者模式实现
可以先看看编译型语言如java中观察者模式的实现,参见博客:
http://www.cnblogs.com/weijunqiang/p/3113828.html
在java中实现一个自己的发布—订阅模式,通常会把订阅者对象自身当作引用传入发布者对象中,同时订阅者还会提供一个诸如update(本例中是seeMail)的方法,供发布者在合适的时候调用。在Javascript中,可以使用注册回调函数的方式来代替传统的发布—订阅模式,更加简单和优雅。
三、一个通用的发布-订阅模式
var events=(function(){ var clientList={}; var listen=function(key,fn){ if(!clientList[key]){ clientList[key]=[]; } clientList[key].push(fn); }; var trigger=function(){ var key=[].shift.apply(arguments); var fns=clientList[key]; if(!fns||fns.length==0){ return false; } for(var i=0;i<fns.length;i++){ fns[i].apply(this,arguments); } }; var remove=function(key,fn){ var fns=clientList[key]; if(!fns){ return false; } if(!fn){ fns.length=0; return; } for(var i=0;i<fns.length;i++){ if(fn===fns[i]){ fns.splice(i,1); } } }; return{ listen:listen, trigger:trigger, remove:remove, }; })(); var installEvent=function(obj){ for(var i in events){ obj[i]=events[i]; } };//该函数可以给所有对象添加动态发布功能
四、发布——订阅模式示例(网站登录)
//现在需要实现网上商城,网站有header头部,nav导航,消息列表,购物车等, //这些模块有一个共同的特征,需要ajax获取到用户信息之后才能进行渲染,如header显示用户头像等等 //1,实现login对象,作为发布者 var login={}; installEvent(login); $.ajax('http://www.bobo.com',function(data){ login.trigger('loginSucc',data); }); //各个模块监听登陆成功的消息 var header=(function(){ login.listen('loginSucc',function(data){ header.setAvatar(); });//监听登陆成功时间 return { setAvatar:function(data){ console.log('设置header模块'); } }; })(); var nav=(function(){ login.listen('loginSucc',function(data){ nav.setAvatar(); }); return { setAvatar:function(data){ console.log('设置nav模块'); } }; }();