javascript 观察者模式实现

观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式)是软件设计模式的一种。在此种模式中,一个目标物件管理全部相依于它的观察者物件,而且在它自己的状态改变时主动发出通知。这一般透过呼叫各观察者所提供的方法来实现。此种模式一般被用来实现事件处理系统。javascript

基本简介

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面能够做为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每一个类将重点放在某一个功能上,而不是其余方面。一个对象只作一件事情,而且将他作好。观察者模式在模块之间划定了清晰的界限,提升了应用程序的可维护性和重用性。java

观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,全部依赖于它的对象都获得通知并自动刷新。编程

因为观察者模式有诸多优势,他在平常编程中随处可见,好比响应事件,做为一名程序猿,掌握他是责无旁贷的责任。设计模式

代码实现

function subject() {
    if (!(this instanceof subject)) {
        return new subject();
    }
    this._eventList = {};
}
subject.prototype = {
    /**
     * 注册观察者
     * @param  {string}   eName   [注册的事件名称]
     * @param  {Function} fn      [响应事件的方法]
     * @param  {object}   [scope] [响应事件的方法的上下文对象]
     */
    on: function(eName, fn, scope) {
        if (!eName == null) return;
        if (Object.prototype.toString.call(fn) === '[object Function]') {
            eName = eName.toLowerCase();
            if (!this._eventList[eName]) {
                this._eventList[eName] = [];
            }
            this._eventList[eName].push({
                fn: fn,
                scope: scope || null
            });
        }
    },
    /**
     * 注销观察者 
     * 取消指定方法对指定事件的响应
     * 若是事件为空,注销全部事件的响应
     * 若是方法为空,注销指定事件的全部响应方法
     * @param  {string}   [eName] [注销的事件名称,]
     * @param  {Function} [fn]    [注销的响应事件的方法]
     */
    off: function(eName, fn) {
        if (eName == null) {
            this._eventList = {};
        } else if (fn == null) {
            delete this._eventList[eName]
        } else {
            var fns = this._eventList[eName];
            if (fns && fns.length) {
                for (var l = fns.length; l--;) {
                    if (fns[l] == fn) {
                        fns.slice(l, 1);
                        break;
                    }
                }
            }
        }
    },
    /**
     * 发布订阅事件
     * @param  {string}   eName   [事件名称]
     * @param  {object}   [args]  [事件参数]
     */
    fire: function() {
        var args = Array.prototype.slice.call(arguments);
        var eName = args.shift();
        if (!eName) return;
        eName = eName.toLowerCase();
        var list = this._eventList[eName] || [];
        for (var i = 0, l = list.length; i < l; i++) {
            var dict = list[i];
            var fn = dict.fn;
            var scope = dict.scope;
            fn.apply(scope || null, args);
        }
    }
}
相关文章
相关标签/搜索