javascript 設計模式(觀察者模式)

本系列文章來源於《Javascript設計模式》(張容銘版),作一個記錄。git

最近在學習《Javascript設計模式》一書,對學習過程作一個筆記總結。系列文章你們能夠關注個人我的博客會不定時更新,你們一塊兒學習一塊兒進步。github

概念

觀察者模式:又稱爲發佈-訂閱者模式或者消息機制(媽蛋叫什麼不重要主要是理解意思)。 首先咱們須要把觀察者建立出來,觀察者模式有三部分,設計模式

  • 消息容器
  • 訂閱消息方法
  • 取消訂閱的消息方法
  • 發送訂閱的消息方法
var Observer = (function () {
    // 防止消息隊列報漏而被篡改故將消息容器做爲靜態私有變量保存
    var _messages = {};
    return {
        // 註冊消息接口
        register: function () {

        },
        // 發佈消息接口
        fire: function () {

        },
        // 移除消息接口
        remove: function() {
            
        }
    }
}())
複製代碼

如今咱們來一一實現這三個方法,學習

register

register 的做用是將訂閱者註冊的消息推入到消息隊列中,這裏咱們須要接收兩個參數:消息的類型以及相應的處理動做,ui

// 註冊消息接口
register: function (type, fn) {
    // 消息不存在則建立一個該消息類型
    if (typeof  _messages[type] === 'undefined') {
        _messages[type] = [fn];
    } else { // 若是消息已經存在
        _messages[type].push(fn);
    }
}
複製代碼

fire

fire 的做用是當觀察者發佈一個消息時將全部訂閱者訂閱的消息依次執行。因此這裏要接收兩個參數,消息類型以及動做執行時須要傳遞的參數(這裏type是必須的)this

// 發佈消息接口
fire: function (type, args) {
    // 若是該消息沒有被註冊,則返回
    if (!_messages[type]) {
        return;
    }
    // 定義消息信息
    var events = {
            type: type, // 消息類型
            args: args || {} // 消息攜帶數據
        },
        len = _messages[type].length // 消息動做長度
    // 遍歷消息動做
    for (var i =0 ; i < len; i++) {
        // 依次執行註冊的消息對應的動做序列
        _messages[type][i].call(this, events);
    }
}
複製代碼

remove

remove 的方法是將訂閱者註銷的消息從消息隊列中清除,這裏咱們也須要兩個參數,即消息類型以及須要清除的動做。spa

// 移除消息接口
var Observer = (function () {
    // 防止消息隊列報漏而被篡改故將消息容器做爲靜態私有變量保存
    var _messages = {};
    return {
        // 註冊消息接口
        register: function (type, fn) {
            // 消息不存在則建立一個該消息類型
            if (typeof  _messages[type] === 'undefined') {
                _messages[type] = [fn];
            } else { // 若是消息已經存在
                _messages[type].push(fn);
            }
        },
        // 發佈消息接口
        fire: function (type, args) {
            // 若是該消息沒有被註冊,則返回
            if (!_messages[type]) {
                console.log("沒有註冊該消息")
                return;
            }
            // 定義消息信息
            var events = {
                    type: type, // 消息類型
                    args: args || {} // 消息攜帶數據
                },
                i = 0, // 消息動做循環變量
                len = _messages[type].length // 消息動做長度
            // 遍歷消息動做
            for (; i < len; i++) {
                // 依次執行註冊的消息對應的動做序列
                _messages[type][i].call(this, events);
            }
        },
        // 移除消息接口
        remove: function (type, fn) {
            // 若是消息隊列存在
            if (_messages[type] instanceof Array) {
                // 從最後一個消息動做遍歷
                var i = _messages[type].length - 1;
                for (; i >= 0; i--) {
                    // 若是存在該動做則在消息動做序列中移除相應的動做
                    if (_messages[type][i] === fn) {
                        _messages[type].splice(i, 1);
                        console.log("刪除成功")
                    } else {
                        console.log("刪除失敗不存在相應的動做")
                    }

                }
            } else {
                console.log("消息不存在,沒法移除")
            }
        }
    }
}())
複製代碼

如今咱們來使用咱們的代碼設計

function test1(e) {
    console.log("我是消息" + e.type, e.args.msg);
}

Observer.register('test1', test1)
Observer.fire('test1', {msg: '執行test1'})
Observer.fire('test2', {msg: '執行test1'})

Observer.remove('test1', function () {

})

Observer.remove('test1', test1)

// 我是消息test1 執行test1
// 沒有註冊該消息
// 刪除失敗不存在相應的動做
// 刪除成功
複製代碼

不得不說觀察者模式思想真的仍是很精妙的,又加強了我繼續學習設計模式的信心。code

相關文章
相關標籤/搜索