← 返回题目列表

观察者模式的优缺点是什么?

高频 中等 第 4 / 27 题 更新于 2026/07/28
观察者模式优缺点解耦事件通知

简化版

观察者模式的优点是发布方和订阅方解耦、方便扩展多个响应动作、符合开闭原则;缺点是调用链变隐式、通知顺序和异常处理复杂、观察者过多可能影响性能,还可能出现循环通知和内存泄漏。

详细版

观察者模式的优点:

  1. 降低对象间直接依赖;
  2. 支持一对多通知;
  3. 新增观察者通常不需要修改发布方;
  4. 适合事件驱动和扩展点设计;
  5. 能把主流程和附加动作拆开。

观察者模式的缺点:

  1. 调用链不直观,排查问题要找事件订阅关系;
  2. 观察者执行顺序可能影响结果;
  3. 一个观察者异常可能影响其他观察者;
  4. 同步通知可能拖慢主流程;
  5. 注册后不取消可能造成内存泄漏;
  6. 观察者之间互相触发可能形成循环通知。

面试回答时可以强调:观察者模式适合事件通知和扩展点,但不要把核心强一致流程随意拆成隐式事件链。

完整版教学

一、优点一:降低耦合

观察者模式最大的优点是让发布方不直接依赖所有订阅方。

没有观察者模式时,订单支付成功逻辑可能直接调用短信、积分、日志、营销系统。

使用观察者模式后,订单服务只发布支付成功事件。短信监听器、积分监听器、日志监听器各自响应。

这让主流程更干净,下游扩展也更容易。

二、优点二:方便扩展

新增一个观察者通常不需要修改 Subject。

比如现在支付成功后要新增“推送用户成长值”,只需要新增一个成长值监听器订阅支付成功事件。

这符合开闭原则:对扩展开放,对修改相对关闭。

当然,这个前提是事件本身设计合理。如果事件字段不够,还是可能需要修改事件对象。

三、优点三:适合事件驱动架构

观察者模式是很多事件驱动设计的基础。

它让系统从“直接调用下游”变成“发布事实,让关心这个事实的人响应”。

这种方式特别适合:

  • 非核心附加动作;
  • 多个模块都关心同一个事件;
  • 扩展点机制;
  • 领域事件;
  • 应用内解耦。

四、缺点一:调用链变隐式

观察者模式让代码依赖变少,但也让调用链不再直观。

你看到:

publishEvent(new OrderPaidEvent(orderId));

很难立刻知道有多少监听器会执行、执行顺序是什么、失败会不会影响主流程。

因此项目里需要通过命名、日志、文档或监控把事件链路暴露出来。

五、缺点二:顺序、异常和性能要设计

如果多个观察者有顺序依赖,观察者模式会变复杂。

例如必须先加积分,再发通知,就不能完全随意地把两者拆成无序观察者。要么显式编排顺序,要么把它们合并到同一个流程里。

异常处理也要明确:一个观察者失败是否影响其他观察者?是否影响发布方?

同步通知还会有性能问题。观察者越多,发布事件耗时越长。

六、缺点三:循环通知和内存泄漏

如果观察者处理事件时又修改 Subject,可能触发新的通知,形成循环。

例如 A 事件触发 B,B 又触发 A,如果没有边界控制,就可能无限循环。

内存泄漏则来自注册后不取消订阅。长生命周期 Subject 持有短生命周期 Observer,会导致 Observer 无法释放。

七、解耦收益与隐式链路成本

一个事件连接 6 个观察者,发布者依赖从 6 个具体类降为 1 个事件契约;但一次发布最多触发 6 条隐藏执行路径。

lower compile-time coupling <-> higher runtime topology complexity

这个推演把模式带来的收益和成本放在同一条调用链上。设计评审时既要确认结果正确,也要确认额外层次没有改变原有契约。

八、边界、代价与验证

检查维度应确认的内容
正确性观察者减少的是静态依赖,不会自动减少系统行为数量和运行成本。
适用边界扩展频繁、响应彼此独立时收益大;核心强一致流程若事件化,会让失败边界和排障变模糊。
测试证据覆盖正常路径、异常路径、空值或未知类型,并断言调用次数与顺序
运行成本记录额外对象、调用层数、延迟、线程或内存开销,不用模式名称代替测量

模式落地后要用单元测试验证独立职责,用集成测试验证对象装配和真实调用入口。涉及并发、远程或异步时,还要补充竞态、超时、重复执行与资源释放测试。

易错点:观察者减少的是静态依赖,不会自动减少系统行为数量和运行成本。

九、常见误区与追问

  • 误区:观察者越多,发布者性能完全不受影响。 同步通知通常是 O(n) 遍历,异步也会消耗队列、线程和下游资源。
  • 误区:发布事件天然等于异步和最终一致性。 观察者只定义一对多通知关系;同步还是异步、是否跨进程以及一致性语义都由具体实现决定。
  • 误区:示例代码能运行,就代表模式边界设计正确。 能运行只证明一条路径,仍要检查异常、并发、顺序、生命周期以及新增实现时是否修改稳定代码。
  • 追问:如何改善隐式调用链的可观测性? 记录事件 id、类型、发布点、监听器耗时与结果,并为异步链路传递 trace 上下文。
  • 追问:观察者失败后由谁重试? 模式本身没有答案;同步场景要定义异常传播,异步场景要由执行器、事件总线或消息系统提供重试与死信策略。
  • 追问:怎样验证这套设计没有改变原有语义? 先做基线行为测试,再对新增层验证返回值、异常类型、调用次数和顺序;性能敏感处还要比较改造前后的量化指标。

十、加强记忆

观察者模式的优点是解耦发布方和订阅方、方便一对多扩展;缺点是调用链隐式、顺序和异常处理复杂、同步通知可能拖慢主流程,还要警惕循环通知和内存泄漏。