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订阅者,发布者和订阅者不直接通讯,通过调度中心来传递消息。

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

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui