设计模式:发布订阅

本文深入探讨了发布订阅设计模式(观察者模式)的核心思想,通过创建容器来管理待执行的任务,实现定时通知并执行订阅的方法。提供了jQuery版本的演示和原生JS的手写实现,帮助读者理解该模式的原理及应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发布订阅设计模式(观察者模式)

思想:准备一个容器,把到达指定时候到处理的事情,事先一一加入到容器中(发布计划,并且向计划表中订阅方法),当到达指定时间点,通知容器中的方法依次执行即可。

jQ版本demo演示效果:

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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值