观察者和发布订阅者模式

尽管观察者模式和发布订阅模式在某些方面相似,但它们在设计和使用上有一些关键的区别。以下是详细的对比:

  • 使用示例
javascript 复制代码
//观察者模式
class Subject { 
    constructor() { 
        this.observers = []; 
    } 
    addObserver(observer) { 
        this.observers.push(observer); 
    } 
    removeObserver(observer) { 
        this.observers = this.observers.filter((obs) => obs !== observer); 
    } 
    notify(data) { 
        this.observers.forEach((observer) => observer.update(data)); 
    } 
} 

class Observer { 
    constructor(name) { 
        this.name = name; 
    } 
    update(data) { 
        console.log(`${this.name} received data: ${data}`); 
    } 
} 

const subject = new Subject(); 
const observer1 = new Observer('Observer 1'); 
const observer2 = new Observer('Observer 2'); 
subject.addObserver(observer1); 
subject.addObserver(observer2); 
subject.notify('Hello Observers!'); 
// 输出: Observer 1 received data: Hello Observers! 
// Observer 2 received data: Hello Observers!
js 复制代码
//发布订阅模式
class EventEmitter { 
    constructor() { 
        this.events = {}; 
    } 
    subscribe(eventName, callback) { 
        if (!this.events[eventName]) { 
            this.events[eventName] = []; 
        } 
        this.events[eventName].push(callback);
    } 
    unsubscribe(eventName, callback) { 
        if (this.events[eventName]) { 
            this.events[eventName] = this.events[eventName].filter( (cb) => cb !== callback ); 
        } 
    } 
    publish(eventName, ...args) { 
        if (this.events[eventName]) { 
            this.events[eventName].forEach((callback) => { callback(...args); });
        }
    }
} 
const ee = new EventEmitter(); 
ee.subscribe('click', (arg) => { 
    console.log('click1' + arg); 
}); 
ee.publish('click', 121212); // 输出: click1121212   
  • 定义和角色
    • 观察者模式
      • 核心角色:

        Subject(主题):维护一个观察者列表,提供添加、删除观察者的方法,并在状态变化时通知所有观察者。

        Observer(观察者):定义一个更新接口,当主题状态变化时,观察者通过该接口接收通知并进行相应处理

      • 关系

        观察者和主题之间存在直接的依赖关系。观察者需要知道主题的存在,并且主题需要知道观察者的具体接口

    • 发布订阅模式
      • 核心角色:

        Publisher(发布者):发布事件或消息,但不需要知道订阅者的存在。

        Subscriber(订阅者):订阅特定事件或消息,并在事件发生时接收通知。

        Event Channel(事件通道:作为发布者和订阅者之间的中介,负责事件的分发。

      • 关系

        发布者和订阅者之间没有直接的依赖关系。发布者只需知道如何通过事件通道发布事件,而订阅者只需知道如何订阅和处理事件。

  • 解耦成都
    • 观察者模式
      • 耦合度较高:主题需要知道观察者的具体接口(如 update 方法),观察者也需要知道主题的存在。
      • 适用场景:适用于对象之间的关系相对固定且已知的情况
    • 发布订阅模式
      • 耦合度较低:发布者和订阅者之间通过事件通道进行通信,彼此不需要直接知道对方的存在。
      • 适用场景:适用于需要高度解耦的系统,特别是在大型系统中,组件之间的依赖关系复杂时。
  • 灵活性
    • 观察者模式
      • 灵活性有限:主题和观察者之间的关系是固定的,难以动态地添加或移除观察者。
      • 适用场景:适用于简单的、关系固定的场景。
    • 发布订阅模式
      • 灵活性高:可以动态地添加或移除订阅者,事件通道可以处理多种类型的事件。
      • 适用场景:适用于复杂的、需要动态管理的系统。
相关推荐
用户0595401744614 小时前
Redis缓存回滚踩坑实录:一个配置失误,让我在凌晨3点丢了3000条数据
前端·css
kyriewen14 小时前
别再这样写条件渲染了——你的React组件里藏着这5种定时炸弹
前端·javascript·react.js
IT_陈寒15 小时前
Redis缓存击穿把我坑惨了,原来这样设过期时间才靠谱
前端·人工智能·后端
用户9385156350715 小时前
从"坐电梯"到"前端路由"——深入理解 Hash 路由原理
前端·typescript·全栈
梦想CAD控件15 小时前
网页端CAD的图形选择、编辑与夹点操作教程
前端·javascript·node.js
妙码生花15 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十二):管理员权限检查中间件,AI 随意放行预闯大祸
前端·后端·go
月月大王的3D日记16 小时前
Three.js 入门系列(8):六种光源全解析 —— 关灯了,开光!
前端·javascript
属于自己的天空16 小时前
每天省去重复 Prompt:我用 Skills 把 CRUD 生成标准化了
前端·后端
卡卡罗特AI16 小时前
GitHub怎么用?零基础,保姆级使用教程-上!建议收藏
前端·后端·github