观察者模式(Observer):又被称作发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主题对象与观察者之间的功能的耦合。

创建观察者对象,有一个消息容器,三个方法:订阅消息方法,取消订阅方法,发送订阅的消息方法

// 将观察者放在闭包中,当页面加载就立即执行
var Observer = (function(){
    //防止消息队列被暴漏而被篡改所以将消息容器作为静态私有变量保存
    var __messages = {};
    return {
        //注册信息接口
        regist :function(){},
        //发布信息接口
        fire : function(){},
        //移除信息接口
        remove : function(){}
    }
})()

1.注册regist

注册方法的作用是将订阅者注册的消息推入到消息队列中。接收两个参数:消息类型以及响应的处理动作,在推入消息队列时如果消息不存在,则创建一个该消息类型并将消息放入消息队列中,如果存在则应该将消息执行方法推入该消息对应的执行方法队列中,目的是保证多个模块注册同一消息能顺利执行。

regist : function(type,fn){
    //如果消息不存在则创建一个该消息类型
    if(typeof __message[type] === 'undefined'){
        //将动作推入到该消息对应的动作执行队列中
        __messages[type] = [fn];
    }else{
        __messages[type].push(fn);
    }
}

2.发布fire

发布消息方法,功能是当观察者发布一个消息时将所有订阅者订阅的消息依次执行。接收两个参数:消息类型以及动作执行时需要传递的参数,消息类型是必须的,在执行消息动作队列之前校验消息的存在很有必要,然后遍历消息执行方法队列,依次执行,将消息类别以及传递的参数打包后一次传入消息执行方法中。

fire : function(type,args){
    //如果消息没有被注册,则返回
    if(!__messages[type]) return;
    //定义消息信息
    var events = {
        type : type,
        args : args || {}
    }
    // 遍历消息动作
    for(var i=0;i<__messages[type].length;i++){
        // 依次执行注册的消息对应的动作序列
        __messages[type][i].call(this,events);
    }
}

3.移除remove

移除注销方法,功能是将订阅者注销的信息从消息队列中清除,也需要两个参数:消息类型以及执行的某一动作,为了避免删除消息动作时消息不存在情况的出现,对消息队列中消息的存在性校验也是很有必要的。

remove : function(type,fn){
    //如果不存在就直接return
    if(!__messages[type]) return;
    //从最后一个消息动作遍历
    for(var i=__messages[type].length-1;i>=0;i--){
        __message[type][i] === fn && __messages[type].splice(i,1);
    }
}

观察者模式可以解决团队开发中最重要的模块间通信问题,是模块间解耦的一种可行方案。