在Java中观察者模式的作用是什么_JavaObserverPattern说明

观察者模式解决一对多依赖中被观察者与观察者高度耦合的问题,通过抽象通知逻辑实现松耦合、可扩展;Java 9起Observer/Observable被废弃,推荐自定义泛型接口并注意线程安全、遍历快照、异常防护等细节。

观察者模

式解决什么问题

当一个对象的状态变化需要通知多个其他对象,且这些对象的类型、数量不确定时,硬编码调用每个监听者的更新方法会导致高度耦合。观察者模式把“谁来响应变化”从被观察者中剥离出来,让通知逻辑可插拔、可扩展。

Java标准库里的 ObserverObservable 已废弃

Java 9 开始,java.util.Observer 接口和 java.util.Observable 类被标记为 @Deprecated,官方明确不推荐使用。原因包括:缺乏泛型支持、线程安全设计模糊、继承强制(Observable 是类,不是接口)、无法组合复用。

替代方案是自己定义接口或使用第三方库(如 RxJava),但最轻量常用的是自定义两个接口:

public interface Observer {
    void update(T data);
}

public interface Subject observer);
    void unregister(Observer observer);
    void notifyObservers(T data);
}

手动实现时容易忽略的三个细节

实际写 Subject 实现类时,这几个点常引发 bug:

  • register()unregister() 必须用线程安全的集合(如 Collections.synchronizedSet(new HashSet())CopyOnWriteArraySet),否则多线程注册/取消时可能抛 ConcurrentModificationException
  • notifyObservers() 遍历时不能直接在循环里调用 observer.update() 并同时修改观察者列表(比如某个 update() 内部又触发了 unregister())——应先复制当前观察者快照再遍历
  • 如果 update() 可能抛异常,不加防护会导致后续观察者收不到通知;建议用 try-catch 包裹单个通知调用,而不是整个循环

什么时候不该用观察者模式

它不是万能的通知机制:

  • 观察者之间有严格执行顺序要求?→ 模式本身不保证顺序,需额外控制(如按注册顺序存储 + 显式排序)
  • 通知必须同步完成,且调用方要等所有观察者处理完才继续?→ 默认是同步阻塞,但若某观察者耗时长,会拖慢主流程;这时应考虑异步化(如提交到 ExecutorService)或换用事件总线(如 Spring ApplicationEvent
  • 只是两个对象之间的简单回调?→ 直接传 Runnable 或函数式接口更轻量,没必要引入完整模式

真正需要观察者的地方,是那种“一对多、松耦合、动态增减监听者”的场景,比如 UI 组件状态变更、配置热更新、日志审计钩子——但实现时得绕开 JDK 那套废弃 API,自己控住细节。