观察者模式,发布订阅者模式

1 观察者模式

定义:观察者模式,又叫发布订阅者模式,又叫消息系统,又叫消息机制,又叫自定义事件,解决主体与观察者之间的耦合问题。
观察者模式是一个行为型设计模式
特点:
1 解决的是耦合问题(类与类之间,对象之间,类与对象之间,模块之间)
2 对于任何一个观察者来说,其它观察者的改变不会影响自身
3 对于任何一个对象来说,既可以是观察者,也可以是被观察者
如:jQuery中的观察者模式。$.CallBack()方法执行的结果得到一个观察者对象,观察者对象有一个方法叫add,用来订阅消息的。观察对象有一个方法叫fire,用来发布消息

2 实现观察者模式

观察者对象必须具备两个方法
on 用来注册消息
第一个参数表示消息的名称,第二个参数表示回调函数
trigger 用来触发消息
第一个参数表示消息的名称,从第二个参数开始表示传递数据
off 用来移除消息的方法,参数同register
once 单次订阅方法,参数同register
通过闭包将接口返回,那么on和trigger对用户来说就是可以访问的,闭包里面存储消息队列,对用户来说就是不可见的,因此是安全

<script>
    // 观察者模式又叫发布订阅者模式,消息系统,消息机制,自定义事件
    var Observer = (function() {
        // 消息队列
        var _msg = {};
        // 暴漏接口
        return {
            /***
             * 订阅消息
             * @type    消息名称
             * @fn      回调函数
             * 将消息回调函数,存储在消息队列中
             * **/
            on: function(type, fn) {
                if (_msg[type]) { // 如果存在type类型的消息,直接添加回调函数
                    _msg[type].push(fn);
                } else {
                    _msg[type] = [fn]; // 否则创建一个type类型的消息,对应回调函数
                }
            },

            /***
             * 发布消息
             * @type    消息类型
             * 从第二个参数开始,表示执行消息回调函数的时候,传递的参数
             * 遍历该类型的消息回调函数,并统一执行
             * **/
            trigger: function(type) {
                if (_msg[type]) {
                    // 获取传递的参数   借助数组的slice方法
                    var args = Array.prototype.slice.call(arguments, 1);
                    // 遍历消息管道,逐一执行每一个方法
                    for (var i = 0; i < _msg[type].length; i++) {
                        // args是一个数组,借助apply将数组中参数传递给函数
                        _msg[type][i].apply(null, args);
                    }
                }
            },

            /**
             * 注销消息
             * @type    消息名称
             * fn       回调函数    注意:匿名函数无法注销
             * 从消息队列中,移除该回调函数
             * ***/
            off: function(type, fn) {
                // 没有传递参数,清空消息队列
                if (type === undefined) {
                    _msg = {};
                    return;
                }
                if (fn) {
                    // 传递了type和fn,从该类型的消息管道中,找到fn,并将其移除
                    for (var i = _msg[type].length - 1; i>=0; i--) {
                        if (_msg[type][i] === fn) {
                            _msg[type].splice(i, 1);
                            return;
                        }
                    }
                } else {
                    // 传递了type,清空该类型的消息管道
                    _msg[type] = [];
                }
            },

            /***
             * 单次订阅
             * @type    消息名称
             * fn       回调函数
             * 注册后将其移除
             * **/
            once: function(type, fn) {
                var me = this;
                // 包装函数
                function callback() {
                    // 注销回调函数,防止无限循环
                    me.off(type, callback);
                    // 执行回调函数,并传递参数
                    // apply第二个参数可以是数组,也可以是类数组对象
                    fn.apply(null, arguments);
                };
                // 订阅
                this.on(type, callback);
            }
        }
    })()

    // function demo() {
    //     console.log('hello');
    // };
    // Observer.on('event', demo);
    // Observer.on('event', demo);
    // Observer.on('demo', demo);

    // Observer.off('event', demo);
    // Observer.off('event', demo);

    Observer.once('event', function() {
        console.log(arguments);
    })

    Observer.trigger('event', 100, 200, true, 'hello');
    Observer.trigger('event', 100, 200, true, 'hello');
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值