js 观察者模式和发布订阅模式的实现和区别

观察者模式

观察者模式中有两个重要元素,一个是主体(subject)一个是观察者(observer)。其中主体(subject)有删除,添加和通知等方法。观察者可以去更新等操作。

下面简单实现观察者模式:

js 复制代码
 class Subject{ // 主体
    constructor(){
        this.observers =[];
    }
    add(observer){
        this.observers.push(observer)
    }
    remove(observer){
        const index = this.observers.findIndex(item=>item===observer)
        if(index!=-1){
            this.observers.splice(index, 1);
        }
    }
    notify(){
        this.observers.forEach(item=>item.update());
    }
    
}

class Observer{  // 观察者
    constructor(name){
     this.name =name;
    }
    update(){
        console.log(this.name)
    }
}

//测试
let subject = new Subject();
let obsDog = new Observer('dog');
let obsCat = new Observer('cat');
sub.add(obsDog);
sub.add(obsCat);
sub.notify();

上述代码中,我们创建了 Subject 对象和两个 Observer 对象,当有关状态发生变更时则通过 Subject 对象的 notify 方法通知这两个 Observer 对象,这两个 Observer 对象通过 update 方法进行更新

发布订阅模式

发布订阅模式 主要有一个调度中心,有订阅,发布,取消订阅等方法。

订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码

下面简单实现发布订阅模式

js 复制代码
class PubSub {
    constructor() {
        this.subs = {}
    }
    // 订阅方法
    subscribe(key, fb) {
        if (!this.subs[key]) {
            this.subs[key] = [];
        }
        this.subs[key].push(fb);
    }
    // 发布方法
    publish(...arg) {
        let args = arg;
        let key = args.shift(); //取出key值
        let fns = this.subs[key];
        if(!fns || fns.length<=0) return;
        if (this.subs[key]) {
            this.subs[key].forEach(cb => cb(...args))
        }
    }
    // 取消订阅方法
    unsubscribe(key, cb) {
        if (this.subs[key]) {
            const cbIndex = this.subs[key].findIndex(e=> e === cb)
            if (cbIndex != -1) {
                this.subs[key].splice(cbIndex, 1);
            }
        }
        if (this.subs[key].length === 0) {
            delete this.subs[key];
        }
    }
    unsubscribeAll(key) {
        if (this.subs[key]) {
            delete this.subs[key];
        }
    }
}

// 测试:
const pubSub = new PubSub();
pubSub.subscribe('封神第一部', time => {
    console.log(`封神第一部开始时间${time}点`);
  })
  pubSub.subscribe('封神第二部', time => {
    console.log(`封神第二部开始时间${time}点`);
  })
  pubSub.publish('封神第一部', 7);  
  pubSub.publish('封神第二部', 11);

通过上面的实现我们发现观察者模式其实是一种直接通讯的方式,比如我们订阅了电影院的微信公众号,当电影院的每种电影上映时,都会对他的所有订阅者发起通知(notify)。

但是在发布订阅模式中多了一个调度中心,比如我们关注了电影院的微信公众号,A同学给电影院发消息只想看封神第一部这个电影,B同学给电影院发消息只想看孤注一掷。那么电影院就会在对应的电影上映时给对应的同学发送不同的消息。,A同学就只接收到封神第一部的开映时间,B同学只接收孤注一掷的开映时间。

总结:

观察者模式有观察者和主体,Subject中通过observers记录ObServer。

优点是:角色明确,Subject和Object要遵循约定的成员方法. 缺点是紧耦合

发布订阅模式有 Publisher发布者、调度中心、Subscribe订阅者,发布者和订阅者不直接通讯,通过调度中心来传递消息。

优点是松散耦合,灵活度高,通常应用在异步编程中, 缺点是:当事件类型变多时,会增加维护成本

相关推荐
营赢盈英6 分钟前
OpenAI API key not working in my React App
javascript·ai·openai·reactjs·chatbot
吕永强38 分钟前
HTML表单标签
前端·html·表单标签
范特西是只猫1 小时前
echarts map地图动态下钻,自定义标注,自定义tooltip弹窗【完整demo版本】
前端·javascript·echarts
麒麟而非淇淋1 小时前
AJAX 进阶 day4
前端·javascript·ajax
图灵苹果1 小时前
【个人博客hexo版】hexo安装时会出现的一些问题
前端·前端框架·npm·node.js
IT-陈2 小时前
app抓包 chrome://inspect/#devices
前端·chrome
hahaha 1hhh5 小时前
Long类型前后端数据不一致
前端
代码搬运媛5 小时前
el-table 如何实现行列转置?
javascript·vue.js·elementui
+码农快讯+6 小时前
JavaScript 基础 - 第17天_AJAX综合案例
开发语言·javascript·ajax