设计模式——观察者模式

一、适用场景

观察者模式,适用于有多个模块存在的,并且模块之间存在相互依赖或者相互通信的情况。使用观察者模式,可以降低耦合度,便于后期程序的扩展和维护。

二、实现原理

观察者模式是怎样做到模块间松散耦合,并且又不影响相互协作的呢?答案就是“观察者(observer)”。在JavaScript中,观察者是一个对象,该对象暴露3个函数给外部,分别是 publish() 、subscribe() 、unsubscribe(),它们分别用于推送通知、订阅消息、撤销订阅。模块之间通过观察者进行通信,而不直接与其他模块关联。具体流程如下:

假定有两个模块A和B,A是一个异步模块,负责从后台获取数据,B是另一个模块,负责展示数据到页面。观察者模式下,它们这样协作:
(1)模块B通过调用观察者(observer)的subscribe() 方法,订阅模块A的消息。就像模块B对观察者说:“Hey, man,如果模块A有什么消息,请马上告诉我。”
(2)模块A在获取到后台数据后,调用观察者(observer)的publish()方法,告诉observer:“Hey, buddy,我拿到数据了。”
(3)观察者(observer)收到消息后,告诉模块B:“模块A那家伙刚刚跟我说它拿到数据了,数据是什么什么balabala……”
(4)模块B拿到观察者(observer)给的数据后,做自己该做的事情。

三、代码分享

下面是一个观察者(observer)的代码:

var observer = (function(){
    var events = {};
    return {
        //定义 subscribe() 方法,用于订阅某个事件名称,当订阅的事件发生时,调用相应的回调函数
        subscribe: function (eventName,callback) {
            if(!events.hasOwnProperty(eventName)){
                events[eventName] = [];
            }
            events[eventName].push(callback);
        },
        //定义 unsubscribe() 方法,用于取消订阅,移除一个给定的函数
        unsubscribe: function(eventName,callback){
            var index = 0;
            var len = 0;
            if(events.hasOwnProperty(eventName)){
                len = events[eventName].length;
                for(;index < len;index++){
                    if(events[eventName][index] === callback){
                        events[eventName].splice(index,1);
                        break;
                    }
                }
            }
        },
        //定义 publish() 方法,用于发布消息(eventName),发布后,对应的回调函数将全部执行
        //调用这个 publish() 方法时,传入的第一个参数必须是事件名称(eventName),后面可传入任意数量的参数
        publish: function(eventName){
            //除了第一个参数(即事件名称)外,将调用 publish() 函数的其他所有参数保存为一个数组
            var data = Array.prototype.slice.call(arguments,1);
            var index = 0;
            var len = 0;
            if(events.hasOwnProperty(eventName)){
                len = events[eventName].length;
                for(;index < len;index++){
                    events[eventName][index].apply(this,data);
                }
            }
        }
    };
})();

self.observer = observer;

下面是一个使用观察者的例子:

//假设这是模块A,向后台请求数据
$.ajax({
    url: "test.action", 
    data:{},
    success: function(r){
        //请求成功后,调用观察者的publish() 方法
        observer.publish('queryData',r);
    }
});

上面的代码不会发生任何事情,直到模块B订阅了“queryData”消息。如下:

var showData = function(type,r){
    var content = "";
    if(r.result){
        content = r.result;
    }
    else{
        content = "No Data!"
    }
    $('#text').val(content);
}
observer.subscribe('queryData',showData );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值