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

相关文章
相关标签/搜索