观察者模式(Observer Pattern)与发布-订阅模式(Publish-Subscribe Pattern)是两种常用于解耦组件通信的设计模式,其核心差异与对比如下:
1. 核心差异对比
维度 | 观察者模式 | 发布-订阅模式 |
---|---|---|
耦合度 | 松耦合(Subject直接管理Observer) | 完全解耦(通过中间件通信) |
通信方式 | 主题直接调用观察者方法(同步) | 消息经事件通道路由(支持异步) |
角色关系 | 一对多(Subject→Observer) | 多对多(Publisher↔Subscriber) |
实现复杂度 | 较低(无中间件) | 较高(需事件代理/消息队列) |
典型应用 | GUI事件、MVC架构 | 微服务通信、消息队列(如Kafka) |
2. 实现机制差异
观察者模式
javascript
// 主题(Subject)直接管理观察者列表
class Subject {
constructor() {
this.observers = [];
}
addObserver(obs) { this.observers.push(obs); }
notify(data) {
this.observers.forEach(obs => obs.update(data)); // 直接调用观察者方法
}
}
class Observer {
update(data) { console.log(`收到数据: ${data}`); }
}
特点:主题与观察者直接绑定,状态变更时主动遍历调用。
发布-订阅模式
javascript
// 通过事件中心(EventBus)解耦
class EventBus {
constructor() { this.events = {}; }
subscribe(event, callback) {
this.events[event] = this.events[event] || [];
this.events[event].push(callback);
}
publish(event, data) {
(this.events[event] || []).forEach(cb => cb(data)); // 经中间件分发
}
}
// 使用示例
const bus = new EventBus();
bus.subscribe("message", (data) => console.log(data)); // 订阅者
bus.publish("message", "Hello!"); // 发布者
特点:发布者和订阅者仅与事件中心交互,互不知晓对方存在。
️ 适用场景
模式 | 典型用例 |
---|---|
观察者模式 | 按钮点击触发多个UI更新、Vue响应式数据监听 |
发布-订阅模式 | 微服务异步通信、跨组件事件通知(如登录状态全局广播)、消息队列系统 |
注意事项
1.内存泄漏
-
观察者模式:需手动移除无效观察者;
-
发布订阅:订阅者需显式取消订阅(如 unsubscribe())。
2.调试复杂度
- 发布订阅因中间件介入,消息流向追踪更困难。
3.性能开销
- 发布订阅的中间件路由可能引入额外延迟。
设计建议:轻量级同步场景优先观察者模式,分布式/高并发场景首选发布订阅模式。