观察者和发布订阅者模式

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

  • 使用示例
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 方法),观察者也需要知道主题的存在。
      • 适用场景:适用于对象之间的关系相对固定且已知的情况
    • 发布订阅模式
      • 耦合度较低:发布者和订阅者之间通过事件通道进行通信,彼此不需要直接知道对方的存在。
      • 适用场景:适用于需要高度解耦的系统,特别是在大型系统中,组件之间的依赖关系复杂时。
  • 灵活性
    • 观察者模式
      • 灵活性有限:主题和观察者之间的关系是固定的,难以动态地添加或移除观察者。
      • 适用场景:适用于简单的、关系固定的场景。
    • 发布订阅模式
      • 灵活性高:可以动态地添加或移除订阅者,事件通道可以处理多种类型的事件。
      • 适用场景:适用于复杂的、需要动态管理的系统。
相关推荐
撸猫7917 分钟前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、26 分钟前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck1 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
augenstern4162 小时前
webpack重构优化
前端·webpack·重构
海拥✘2 小时前
CodeBuddy终极测评:中国版Cursor的开发革命(含安装指南+HTML游戏实战)
前端·游戏·html
寧笙(Lycode)2 小时前
React系列——HOC高阶组件的封装与使用
前端·react.js·前端框架
asqq82 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩3 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
Hejjon3 小时前
Vue2 elementUI 二次封装命令式表单弹框组件
前端·vue.js
小堃学编程4 小时前
前端学习(3)—— CSS实现热搜榜
前端·学习