登录
首页 >  文章 >  前端

观察者模式与发布订阅区别详解

时间:2026-01-09 12:33:36 227浏览 收藏

IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《JavaScript观察者模式详解与发布订阅区别》,聊聊,我们一起来看看吧!

观察者模式与发布-订阅模式本质区别在于耦合度与通信方式:前者是主体与观察者直接同步调用,后者通过事件总线异步解耦通信。

JavaScript如何实现观察者模式_它和发布订阅模式有何不同

JavaScript 中观察者模式和发布-订阅模式常被混淆,但二者在结构、依赖关系和通信方式上有本质区别。观察者模式强调“一对多”的同步依赖,目标对象(Subject)直接持有观察者(Observer)的引用;而发布-订阅模式通过“事件总线”解耦双方,依赖中介(Event Bus)完成异步消息分发。

观察者模式:主体与观察者直接关联

观察者模式中,被观察的目标(Subject)维护一个观察者列表,当状态变化时,主动遍历并调用每个观察者的更新方法。观察者需显式订阅(attach)和退订(detach),且必须了解 Subject 的存在。

典型实现要点:

  • Subject 提供 addObserverremoveObservernotify 方法
  • Observer 实现统一的 update 接口(或回调函数)
  • Subject 与 Observer 是强引用关系,生命周期易耦合
  • 通知是同步的,执行顺序即注册顺序

例如:DOM 事件监听本质上是观察者模式的变体——元素(Subject)持有事件处理函数(Observer)的引用,触发 click 时同步调用 handler。

发布-订阅模式:靠事件中心解耦通信

发布-订阅模式引入第三方“事件总线”(Event Bus 或 PubSub),发布者(Publisher)只向总线发消息,订阅者(Subscriber)只向总线注册回调。双方互不知晓,也不持有对方引用。

关键特征:

  • 总线提供 on(订阅)、off(取消)、emit(发布)方法
  • 支持按事件类型(如 "user:login")过滤,可一对多、多对多、甚至零对多
  • 消息可缓存、延迟派发,支持异步、队列、中间件等扩展
  • 天然支持跨组件、跨模块通信,常见于 Vue 的 $bus、Node.js 的 EventEmitter

核心差异对比

二者最根本的不同在于耦合程度与通信路径

  • 依赖关系:观察者模式中 Observer 知道 Subject,Subject 也持有 Observer;发布-订阅中 Publisher 和 Subscriber 都只依赖 Event Bus
  • 通信方式:观察者是同步、即时、点对点的;发布-订阅是异步、事件驱动、基于主题(topic)的间接通信
  • 灵活性:发布-订阅支持动态事件名、通配符匹配(如 "user:*")、优先级、once 订阅等,观察者模式通常固定在单一状态变更上
  • 内存管理:观察者若忘记 detach 易导致内存泄漏;发布-订阅虽也需 off,但总线可提供自动清理策略(如组件销毁时批量清除)

简单代码示意

观察者模式简写:

class Subject {
  constructor() { this.observers = []; }
  addObserver(o) { this.observers.push(o); }
  notify(data) { this.observers.forEach(o => o.update(data)); }
}
class Observer { update(data) { console.log('Received:', data); } }

发布-订阅简写:

class EventBus {
  constructor() { this.events = {}; }
  on(type, fn) { (this.events[type] = this.events[type] || []).push(fn); }
  emit(type, data) { this.events[type]?.forEach(fn => fn(data)); }
}

注意:实际项目中推荐使用成熟的库(如 mitt、tiny-emitter)或框架内置机制(React 的 Context + useReducer、Vue 的 provide/inject + emits),避免手写总线带来的边界问题。

到这里,我们也就讲完了《观察者模式与发布订阅区别详解》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>