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);
        }
    }
}
相關文章
相關標籤/搜索