观察者模式在JS的学习过程当中很重要,尤为是最近几年MV*框架的发展。
观察者模式很好的体现了松耦合(Loose coupling)原则和单一职责原则。
观察者模式
它定义了对象间一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖它的对象都将获得通知。
观察者模式由主体和观察者组成,主体负责发布事件,观察者经过订阅事件来观察主体。
主体并不知道观察者的任何事情,观察者知道主体并能注册事件的回调函数。angularjs
代码1:es6
function Emitter(){ this._listerner={};//自定义事件名 } Emitter.prototype.bind=function(eventName,handler){ // var listenersArr=this._listerner[eventName]||[]; // listenersArr.push(handler); // this._listerner[eventName]=listenersArr; if(!this._listerner.hasOwnProperty(eventName)){ this._listerner[eventName]=[]; } this._listerner[eventName].push(handler); } Emitter.prototype.trigger=function(eventName){ if (!this._listerner.hasOwnProperty(eventName)) { console.log('你没绑定这个事件'); return; } var args = Array.prototype.slice.call(arguments, 1); ////args为得到除了eventName后面的参数(最后被用做注册事件的参数) //arguments并非真正的数组对象,只是与数组相似而已,因此它并无slice这个方法 //Array.prototype.slice.call(arguments, 1)能够理解成是让arguments转换成一个数组对象,让arguments具备slice()方法。 //要是直接写arguments.slice(1)会报错 this._listerner[eventName].forEach(function(callback){ callback.call(this,args);//经过这种方法能够传参 }); } function handler1(){ console.log('第一次绑定'); //console.log(arguments); Array.prototype.forEach.call(arguments,function(item){//arguments.forEach(function(item)),arguments为上面trigger中调用它时传进来的参数 console.log(item); }) } function handler2(){ console.log('第二次绑定'); } function handler3(){ console.log('第三次绑定'); } var emitter=new Emitter(); emitter.bind('selfEvent',handler1); emitter.bind('selfEvent',handler2); emitter.bind('selfEvent2',handler3); emitter.trigger('selfEvent',233333333);
代码2(下面这段来自stackoverflow):设计模式
//model function Book(name,isbn){ this.name=name; this.isbn=isbn; } function BookCollection(books){ this.books=books; } BookCollection.prototype.addBook=function(book){ this.books.push(book); $.publish('book-added',book); return book; } BookCollection.prototype.removeBook=function(book){ var removed; if(typeof book==='number'){ removed=this.books.splice(book,1); } for(var i=0;i<this.books.length;i+=1){ if(this.books[i]===book){ removed=this.books.splice(i,1); } } $.publish('book-removed',removed); return removed; } //View var BookListView=(function(){ function removeBook(book){ $('#'+book.isbn).remove(); } function addBook(book){ $(#bookList).append('<div id="'+book.isbn+'">'+book.name+'</div>'); } return { init:function(){ $.subscribe('book-removed',removeBook); $.subscribe('book-added',addBook); } } }());
应用:
1) angularjs的双向数据绑定中,就涉及到了这个设计模式。
angularjs的双向数据绑定主要是利用脏检查来完成的。可是如何把一个model绑定到多个view就是利用观察者模式来作的。数组
2)es6中的Promise的实现过程也使用了观察者模式。app