您现在的位置是:首页 > WEB > JSJS

javascript与jquery中的观察者模式

阿龙2019-06-26【JS】人已围观

简介观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

使用观察者模式的好处:

  1. 支持简单的广播通信,自动通知所有已经订阅过的对象。
  2. 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
  3. 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
jQ版本演示效果:
let $plan = $.Callbacks();//=>创建一个空的计划表:空容器 =>$PLAN
setTimeout(function () {
    $plan.fire(10, 20);//=>FIRE就是通知容器中的方法按照顺序依次执行的:10和20为参数
}, 1000);

$plan.add((x, y) => {//=>ADD是向容器中增加方法  REMOVE是从容器中移除方法
    console.log(1);
});
$plan.add((x, y) => {
    console.log(2);
});
$plan.add((x, y) => {
    console.log(3);
});
原生JS手写发布订阅:

//=>JQ
// let $plan = $.Callbacks();
// $plan.add(function(x,y){});
// $plan.remove(function(){});
// $plan.fire(10,20);

~function anonymous(window) {
    class Subscribe {
        constructor() {
            //=>创建一个容器
            //每一个实例都有一个自己独有的容器,管理自己需要执行的方法即可
            this.pond = [];
        }

        //=>向计划表(POND池子)中增加方法:去重
        //FN:我们需要增加的方法
        add(fn) {
            let pond = this.pond,
                isExist = false;
            pond.forEach(item => item === fn ? isExist = true : null);
            !isExist ? pond.push(fn) : null;
        }

        //=>从计划表(POND池子)中移除方法
        remove(fn) {
            let pond = this.pond;
            pond.forEach((item, index) => {
                if (item === fn) {
                    // pond.splice(index, 1);//=>我们不能基于SPLICE删除,因为这种删除方式会改变原有的数组,例如:我们通知方法执行,当执行到FN3的时候(FIRE循环索引是2),但是基于SPLICE把FN1/FN2删除后,原始数组后面的项都向前提取两位,此时FIRE中继续遍历下一个方法(索引3),已经找不到和他匹配的那一项了

                    //=>让当前项赋值为NULL即可(这样函数移除掉了,但是此时的数组结构没有改变,不会出现数组塌陷的问题)
                    pond[index] = null;//=>item=null是不行的
                }
            });
        }

        //=>通知计划表中的方法依次执行
        //如果传递参数信息了,把这些参数依次赋值给执行的每一个方法
        fire(...arg) {
            let pond = this.pond;
            //=>REMOVE机制处理了,此时ITEM不一定都是函数了,还有可能是NULL
            //NULL的话不执行,而且最好是把这一项删除掉
            for (let i = 0; i < pond.length; i++) {
                let item = pond[i];
                if (item === null) {
                    pond.splice(i, 1);
                    i--;
                    continue;
                }
                item(...arg);
            }
        }
    }

    window.Subscribe = Subscribe;
}(window);


let subscribe = new Subscribe();
let fn1 = function fn1(x, y) {
    console.log(1, x, y);
};
let fn2 = function fn2() {
    console.log(2);
};
let fn3 = function fn3() {
    console.log(3);
    subscribe.remove(fn1);
    subscribe.remove(fn2);
};
let fn4 = function fn4() {
    console.log(4);
};

subscribe.add(fn1);
subscribe.add(fn1);
subscribe.add(fn2);
subscribe.add(fn1);
subscribe.add(fn3);
subscribe.add(fn4);

setInterval(() => {
    subscribe.fire(100, 200);
}, 1000);
以上代码整理于:神三元同学https://blog.csdn.net/weixin_42098339/article/details/90144628

Tags:javascrip   jquery   观察者   发布订阅

支持一下! ()

文章评论

    共有条评论大侠,来闹两句...

    请输入昵称:

    填入验证码:

打赏本站

  • 如果您觉得站长文章不错,可以通过扫码支付打赏一下哦!
  • 微信扫码:您说多少就多少~
  • 支付宝扫码:您说多少就多少~