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

观察者模式解决什么问题
当一个对象的状态变化需要通知多个其他对象,且这些对象的类型、数量不确定时,硬编码调用每个监听者的更新方法会导致高度耦合。观察者模式把“谁来响应变化”从被观察者中剥离出来,让通知逻辑可插拔、可扩展。
Java标准库里的 Observer 和 Observable 已废弃
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:
立即学习“Java免费学习笔记(深入)”;
-
register()和unregister()必须用线程安全的集合(如Collections.synchronizedSet(new HashSet())或CopyOnWriteArraySet),否则多线程注册/取消时可能抛ConcurrentModificationException -
notifyObservers()遍历时不能直接在循环里调用observer.update()并同时修改观察者列表(比如某个update()内部又触发了unregister())——应先复制当前观察者快照再遍历 - 如果
update()可能抛异常,不加防护会导致后续观察者收不到通知;建议用try-catch包裹单个通知调用,而不是整个循环
什么时候不该用观察者模式
它不是万能的通知机制:
- 观察者之间有严格执行顺序要求?→ 模式本身不保证顺序,需额外控制(如按注册顺序存储 + 显式排序)
- 通知必须同步完成,且调用方要等所有观察者处理完才继续?→ 默认是同步阻塞,但若某观察者耗时长,会拖慢主流程;这时应考虑异步化(如提交到
ExecutorService)或换用事件总线(如 SpringApplicationEvent) - 只是两个对象之间的简单回调?→ 直接传
Runnable或函数式接口更轻量,没必要引入完整模式
真正需要观察者的地方,是那种“一对多、松耦合、动态增减监听者”的场景,比如 UI 组件状态变更、配置热更新、日志审计钩子——但实现时得绕开 JDK 那套废弃 API,自己控住细节。










