观察者模式

观察者模式在JS的学习过程中很重要,尤其是最近几年MV*框架的发展。
观察者模式很好的体现了松耦合(Loose coupling)原则和单一职责原则。
观察者模式
它定义了对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知。
观察者模式由主体和观察者组成,主体负责发布事件,观察者通过订阅事件来观察主体。
主体并不知道观察者的任何事情,观察者知道主体并能注册事件的回调函数。

代码1:

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的实现过程也使用了观察者模式。


不能写bug啊
142 声望11 粉丝