观察者模式&发布订阅模式学习

70 阅读2分钟

观察者模式

/**
 * 观察者模式
 * 角色: 观察者:n  目标对象:1
 * 观察者可以接受目标对象发布的信息(update),然后根据信息作出对应的反应
 * 目标对象可以被观察者进行订阅,或者说是目标对象新增(接纳)新的观察者 ===> addObserver
 * 目标对象可以发布任务给当前的观察者队列 ===> notify
 */
// 观察者类
class Observer {
    constructor(name) {
        this.name = name;
    }
    // 获取目标对象的信息
    update({ type, info }) {
        console.log(type, info);
        this.go(info);
    }
    // 观察者的动作
    go(info) {
        console.log(`${this.name} get ${info}`);
    }
}
// 目标对象类
class Subject {
    constructor() {
        this.observeList = [];
    }
    // 新增观察者
    addObserver(observe) {
        this.observeList.push(observe);
    }
    // 发布任务
    notify(task) {
        this.observeList.forEach(observer => observer.update(task));
    }
}

const subject = new Subject();
const observer1 = new Observer('one');
const observer2 = new Observer('two');

// 新增观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

const task1 = {
    type: 'testType',
    info: 'testInfo'
}

subject.notify(task1);

发布订阅模式

/**
 * 发布订阅者模式
 * 角色: 发布者 事件中心 订阅者
 * 发布者给每一种类型的任务新建一个事件处理中心 ===> 订阅方法
 * 发布者可以发布不同类型的任务 ===> 发布任务
 * 对应的任务类型会由对应的事件中心进行处理 ===> 订阅方法的函数参数
 */

class Subscribe {
    constructor() {
        // 事件中心
        this.subscribeCenter = new Map();
    }
    // 订阅方法
    addSubscribe(type, fn) {
        // 如果这个类型的事件中心不存在,那就新增这个事件中心
        if (!this.subscribeCenter.has(type)) {
            this.subscribeCenter.set(type, []);
        }
        /**
         * 防止重复订阅
         * 允许同一类型有不同的操作(方法)
         * 当操作(方法)不同时通过push新增
         */
        if (!this.subscribeCenter.get(type).find(itemFn => itemFn === fn)) {
            this.subscribeCenter.get(type).push(fn);
          }
    }
    // 发布
    publish(type, data) {
        /**
         * 判断当前类型的事件中心是否存在
         * 存在获取当前事件中心的所有订阅者的操作
         * 遍历当前允许的操作,发布任务
         */
        if (this.subscribeCenter.has(type)) {
            const fnList = this.subscribeCenter.get(type);

            fnList.forEach(fn => {
                fn(data);
            });
        }
    }
    /**
     * 取消订阅
     * 取消的是一个类型下的一个操作
     */
    unsubscribe(type, fn) {
        if (this.subscribeCenter.has(type)) {
            const fnList = this.subscribeCenter.get(type);
            if (fnList.length) {
                for (let i = 0; i < fnList.length; i++) {
                    if (fnList[i] === fn) {
                        fnList.splice(i, 1);
                        break;
                    }
                }
            }
        }
    }
    /**
     * 取消全部订阅
     * 取消的是一个类型的事件中心
     */
    unsubscribeAll(type) {
        if (this.subscribeCenter.has(type)) {
            this.subscribeCenter.delete(type);
        }
    }
}
// function callback() {
//     console.log(123);
// }
let subscribe = new Subscribe();
subscribe.addSubscribe('game', function (event) {
    console.log(`game is ${event}`);
})

subscribe.addSubscribe('learn', function (event) {
    console.log(`learn is ${event}`);
});

// 发布任务
subscribe.publish('game', "打游戏")
subscribe.publish('learn', "学习")

观察者模式与订阅发布模式原理相似,基本可以理解为相同原理下的不同写法。

参考学习

观察者模式 vs 发布订阅模式,千万不要再混淆了