马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在软件架构设计中,观察者模式(Observer Pattern)和发布订阅模式(Publish-Subscribe Pattern)都是处理对象间通信的紧张模式,尤其在前端框架、游戏开辟、分布式系统中应用广泛。只管两者常被混淆,但它们有着本质的区别。本文将深入对比这两种模式的实现原理、适用场景及优缺点。
模式界说与核心概念
观察者模式(Observer Pattern)
观察者模式是一种对象间的一对多依赖关系的设计模式,当一个对象(被观察者/Subject)的状态发生改变时,全部依赖于它的对象(观察者/Observers)都会自动收到关照并更新。
关键脚色:
- Subject(被观察者):维护观察者列表,提供注册/注销接口,状态变革时关照观察者
- Observer(观察者):界说更新接口,吸收Subject关照
发布订阅模式(Publish-Subscribe Pattern)
发布订阅模式通过**消息署理(变乱总线)**解耦发布者和订阅者,发布者将消息发布到特定频道,订阅者只吸收感爱好频道的消息。
关键脚色:
- Publisher(发布者):发布消息到变乱通道,不关心订阅者
- Subscriber(订阅者):订阅特定频道,处理消息
- Event Channel(变乱通道):负责过滤和路由消息
核心区别对比
特性观察者模式发布订阅模式耦合度松耦合(但Subject知道Observer存在)完全解耦(两边不知道彼此存在)通信方式直接调用Observer方法通过中间件通报消息关系一对一或一对多多对多同步性通常是同步的可以是异步的实现复杂度较简单较复杂(需中间件)典型应用GUI变乱处理、MVC架构微服务通信、消息队列 代码实现对比
观察者模式实现示例
- // 被观察者
- class Subject {
- private observers: Observer[] = [];
-
- attach(observer: Observer) {
- this.observers.push(observer);
- }
-
- notify(message: string) {
- this.observers.forEach(observer => observer.update(message));
- }
- }
- // 观察者接口
- interface Observer {
- update(message: string): void;
- }
- // 具体观察者
- class ConcreteObserver implements Observer {
- update(message: string) {
- console.log(`收到消息: ${message}`);
- }
- }
- // 使用
- const subject = new Subject();
- const observer = new ConcreteObserver();
- subject.attach(observer);
- subject.notify("状态更新!");
复制代码 发布订阅模式实现示例
- // 事件总线
- class EventBus {
- private channels: Map<string, Function[]> = new Map();
-
- subscribe(channel: string, callback: Function) {
- if (!this.channels.has(channel)) {
- this.channels.set(channel, []);
- }
- this.channels.get(channel)!.push(callback);
- }
-
- publish(channel: string, data: any) {
- const callbacks = this.channels.get(channel);
- callbacks?.forEach(cb => cb(data));
- }
- }
- // 使用
- const bus = new EventBus();
- // 订阅者A
- bus.subscribe("news", (data: string) => {
- console.log(`订阅者A收到新闻: ${data}`);
- });
- // 订阅者B
- bus.subscribe("news", (data: string) => {
- console.log(`订阅者B收到新闻: ${data}`);
- });
- // 发布者
- bus.publish("news", "重大科技突破!");
复制代码 应用场景分析
观察者模式适用场景
- GUI变乱处理
按钮点击→多个UI组件更新
- 游戏开辟
脚色血量变革→更新血条UI、触发音效等
- MVC架构
Model变动→自动更新View
- 状态监控
服务器状态变革→关照监控服务
发布订阅模式适用场景
- 微服务通信
订单服务发布变乱→库存服务、物流服务订阅
- 实时数据处理
传感器数据发布→多个分析服务订阅
- 前端框架状态管理
Vuex/Redux的全局状态变动关照
- 聊天应用
消息发布→多个客户端订阅
性能与复杂度考量
观察者模式
✅ 轻量级,无中间件开销
✅ 实时性强(直接调用)
❌ 观察者过多会影响Subject性能
❌ 观察者与Subject生命周期需手动管理
发布订阅模式
✅ 完全解耦,扩展性强
✅ 支持跨进程/网络通信
✅ 易于实现过滤和路由逻辑
❌ 中间件引入额外延迟
❌ 系统复杂度增长
当代框架中的实现
观察者模式应用
- React的State更新机制
- Java Swing/AWT变乱监听
- C#的delegate/event
发布订阅模式应用
- Redis的Pub/Sub功能
- RabbitMQ/Kafka消息队列
- Vue的EventBus
- Node.js的EventEmitter
怎样选择?
根据项目需求考虑以下因素:
- 耦合度要求
- 须要完全解耦 → 发布订阅
- 适度解耦即可 → 观察者
- 性能要求
- 低延迟关键 → 观察者
- 可接受轻微延迟 → 发布订阅
- 系统规模
- 简单单体应用 → 观察者
- 复杂分布式系统 → 发布订阅
- 通信范围
- 进程内通信 → 两者皆可
- 跨进程/网络 → 发布订阅
常见误区澄清
误区1:“发布订阅只是观察者的别名”
事实:发布订阅通过中间件实现了完全解耦,是更高级的抽象。
误区2:“RxJS是观察者模式的实现”
事实:RxJS实际联合了观察者和迭代器模式,其Observable更靠近发布订阅模型。
误区3:“jQuery的变乱系统是观察者模式”
事实:jQuery的on()/trigger()实际实现了发布订阅模式,DOM元素充当了变乱通道。
演进与混淆模式
在实践中,两种模式常联合使用:
- 观察者+发布订阅混淆
- 相应式编程扩展
- RxJS等库将发布订阅与函数式编程联合
- 添加了操作符、背压处理等高级特性
- 当代前端框架的合成模式
- Vue的相应式系统:Observer + 捏造发布订阅
- React Context API:受限的发布订阅实现
总结
明白两种模式的关键差异在于通信的中介程度:
- 观察者模式像是公司部门内会议:构造者(Subject)直接关照参会者(Observers)
- 发布订阅模式像是行业研讨会:演讲者(Publisher)通过会务组(Event Channel)将信息通报给注册听众(Subscribers)
选择时需权衡耦合度、性能和系统复杂度。对于大多数当代应用,特别是分布式系统,发布订阅模式因其出色的解耦能力成为首选;而在性能敏感或简单场景中,观察者模式仍具上风。掌握这两种模式的本质区别,将帮助开辟者做出更合理的架构决策。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |