美文网首页
观察者和发布订阅模式

观察者和发布订阅模式

作者: 弱冠而不立 | 来源:发表于2021-03-11 23:23 被阅读0次

    观察者模式

    在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

    当Subject(被观察对象)状态发生变化时,会给所有的Observers(观察者们)发送一个通知函数,观察者们接收到通知后通常会调用各自的更新函数。
    代码样例:
    const Sub = function(...obrs) {
        // 这个被观察的对象,收录着被哪些观察者观察
        this.obsevers = [...obrs];
    }
    
    // 添加观察者关注这个对象
    Sub.prototype.add = function(obr) {
        this.obsevers.push(obr)
    }
    
    // 被关注的对象,如果更新了就可以调用这个通知方法,去通知所有的观察者去更新
    Sub.prototype.notify = function() {
        for(let obr of this.obsevers) {
            if(typeof obr.update === 'function') {
                obr.update();
            }
        }
    }
    
    // 例如:
    
    let obj1 = {
        update: () => {
            console.log("update obj1");
        }
    }
    
    let obj2 = {
        update: () => {
            console.log("update obj2");
        }
    }
    
    // 添加观察者
    let sub = new Sub(obj1, obj2);
    
    /** 假设这里有一些操作,使得sub更新了,然后通知所有的观察者去执行它们自己的更新操作 */
    
    // 通知观察者
    sub.notify();
    
    

    发布订阅模式

    消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。它们都依托于中间的事件总线。

    发布者状态更新时,发布某些类型的通知,而中间控制器只通知订阅了相关类型的订阅者。发布者和订阅者之间是没有直接关联的。
    代码样例:
    const EventListener = function() {
        this.map = new Map();
    }
    
    /**
     * 订阅消息
     * @param {any} e 订阅的消息类型
     * @param {function} fn 订阅后,如果有消息时,需要触发的方法
     */
    EventListener.prototype.on = function(e, fn) {
    
        // 判断是否已经有了订阅的消息类型,有的话就把订阅的方法传入,否则就新建类型
        let eventList = this.map.get(e);
        if(!eventList) {
            this.map.set(e, [fn])
        } else {
            eventList.push(fn);
        }
    }
    
    /**
     * 发布消息
     * @param {any} e 订阅的消息类型
     * @param  {...any} arg 发布出去的消息
     */
    EventListener.prototype.emit = function(e, ...arg) {
    
        // 找到发布的消息类型,然后发布消息
        let eventList = this.map.get(e);
        if(eventList) {
           for(let fn of eventList) {
               fn(...arg);
           } 
        } else {
            return false;
        }
    }
    
    // 例如
    
    let eventListener = new EventListener();
    
    
    let user1 = {
        // user1 更新消息后的回调
        update: (...msg) => {
            console.log("课程更新记录:", ...msg);
        }
    }
    
    let user2 = {
        // user2 更新消息后的回调
        update: (...msg) => {
            console.log("游戏更新记录:", ...msg);
        }
    }
    
    // 分别订阅不同的类型的事件
    eventListener.on("class", user1.update)
    eventListener.on("game", user2.update)
    
    // 推送不同类型事件的更新消息
    eventListener.emit("class", "计算机网络", "毛概")
    eventListener.emit("game", "原神")
    

    相关文章

      网友评论

          本文标题:观察者和发布订阅模式

          本文链接:https://www.haomeiwen.com/subject/hqibqltx.html