观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。
发布/订阅模式(Pub/Sub)是一种消息模式,它有 两个参与者 : 发布者和订阅者 。发布者向 某个信道发布一条消息,订阅者绑定这个信道,当有消息发布至信道时就会 接收到一个通知。最重要的一点是, 发布者和订阅者是完全解耦的,彼此并不知晓对方 的存在。两者仅仅共享一个信道名称。
从定义上可以看出,发布订阅模式里双方是完全解耦的,而在观察者模式里,目标对象管理这观察者,双方是耦合的,这是最主要的区别,而在发布订阅模式中多了一个中间层信道。
我们从简单的代码开始,以Dog对象的fire方法来呈现两者的不同:
观察者模式
function Dog(){ this.handles = {};//保存所有观察者方法的引用 } Dog.prototype.addHandle = function(type,func){ if(!(this.handles[type] instanceof Array)){ this.handles[type] = []; } this.handles[type].push(func); } Dog.prototype.fire = function(type){ var typeFunc = this.handles[type]; var len = typeFunc.length; for(var i = ;i < len; i++){ typeFunc[i](event); } } Dog.prototype.removeHandle = function(type,func){ var typeFunc = this.handles[type]; if(!(typeFunc instanceof Array)){ return; } var len = typeFunc.length; for(var i = ;i < len; i++){ if(typeFunc[i] == func){ typeFunc.splice(i,1); } } }
发布订阅模式实现
function rockets(){//信道 this.subers = {}; } rockets.prototype.addSub = function(type,func){ if(!(subers[type] instanceof Array)){ subers[type] = []; } subers[type].push(func); } rockets.prototype.removeSub = function(type,func){ var typeFunc = subers[type]; if(!(typeFunc instanceof Array)){ return; } var len = typeFunc.length; for(var i = ;i < len; i++){ if(typeFunc[i] == func){ typeFunc.splice(i,1); } } } rockets.prototype.fire = function(type){ var typeFunc = subers[type]; var len = typeFunc.length; for(var i = ;i < len; i++){ typeFunc[i](event); } } function Dog(){ this.rockets = new rockets(); } Dog.prototype.fire = function(type){ this.rockets.fire(type); }
从中可以看出发布订阅模式相对观察者模式多了一个中间层从而把发布和订阅分开,如果从这点代码量看来好像发布订阅完全多此一举,但是在大型项目中的团队合作来说,完全解耦是十分有必要的。