面试题答案
一键面试相同点
- 目的一致:观察者模式和发布订阅模式都是为了实现对象间的事件通信,当一个对象状态发生变化时,能够通知到其他相关对象。
不同点
- 耦合度:
- 观察者模式:目标对象(被观察对象)和观察者之间直接关联,耦合度较高。目标对象需要维护一个观察者列表,直接调用观察者的更新方法。
- 发布订阅模式:发布者和订阅者之间通过消息代理(中介者)进行通信,耦合度较低。发布者和订阅者都只与消息代理交互,彼此不知道对方的存在。
- 触发通知方式:
- 观察者模式:目标对象状态改变时,直接主动通知观察者。
- 发布订阅模式:发布者发布消息后,由消息代理负责将消息推送给订阅了该消息的订阅者。
- 灵活性:
- 观察者模式:相对较固定,观察者必须提前注册到目标对象上。
- 发布订阅模式:更灵活,订阅者可以在任何时候订阅或取消订阅消息,发布者也无需关心订阅者的具体情况。
优先选择观察者模式的场景
- 实时数据更新场景:例如在一个简单的仪表盘应用中,需要实时显示数据变化。仪表盘组件作为目标对象,多个显示数据的小部件作为观察者。由于数据变化需要立即反映在相关组件上,且组件之间关系较为明确,使用观察者模式可以直接、高效地实现数据更新,减少中间环节带来的开销。
- 组件间紧密关联场景:在一个自定义的 UI 组件库中,一个父组件的状态变化会直接影响到其内部特定的子组件。比如一个折叠面板组件,当面板展开或折叠状态改变时,需要其子组件(如标题、内容区域等)做出相应调整,此时观察者模式可以很好地满足需求,因为组件间耦合度较高且交互明确。
优先选择发布订阅模式的场景
- 大型应用中解耦模块:在一个大型的电商应用中,购物车模块、订单模块、支付模块等可能分布在不同的代码库或微服务中。当用户完成支付后,需要通知购物车模块更新商品库存,通知订单模块更新订单状态等。由于这些模块之间耦合度应尽量降低,使用发布订阅模式通过消息队列等消息代理可以很好地实现解耦,各模块只需关注自己订阅的消息,而无需关心其他模块的具体实现和调用关系。
- 异步事件处理场景:例如在一个基于 Node.js 的日志系统中,不同的日志处理逻辑(如记录到文件、发送到远程服务器、在控制台打印等)可能需要异步执行。使用发布订阅模式,当有新日志产生时,发布者发布日志消息,各个订阅者(不同的日志处理逻辑)可以异步地处理该消息,互不干扰,提高系统的整体性能和灵活性。