观察者模式通过被观察者(subject)主动广播状态变更、观察者(observer)被动响应,实现低耦合事件通知;核心是接口定义、泛型监听器集合、弱引用防泄漏、线程安全容器及异常隔离,并优先复用spring、livedata或kafka等框架机制。

观察者模式是构建系统内事件通知机制最自然、最常用的设计方案。它不依赖轮询或硬编码调用,而是让状态变化“主动广播”,让关心结果的模块“被动响应”,从而实现低耦合、高可维护的通知体系。
明确核心角色分工
先理清两个关键角色的职责边界:
- 被观察者(Subject):只管“有事发生”——它持有观察者列表,提供注册(attach)、注销(detach)方法,并在状态变更后调用 notify();它不关心谁在听、怎么处理,也不持有观察者的业务逻辑。
- 观察者(Observer):只管“听到就做”——它实现统一的回调接口(如 update(Event event)),收到通知后执行自身逻辑;它不关心事件从哪来、是否还有别人在听,也不影响被观察者运行。
用接口+集合实现松耦合通信
避免继承限制和类型僵化,推荐用组合方式实现:
- 定义一个泛型事件监听接口:interface EventListener
{ void onEvent(T event); } - 被观察者内部用 List
> 存储订阅者,而非具体类类型 - 注册时传入 lambda 或方法引用,例如:subject.addListener((e) -> sendSms(e.getOrderNo()));
- 通知时遍历列表调用,不强求所有观察者同步执行,可配合线程池异步分发
注意生命周期与线程安全细节
实际落地时容易出问题的三个点:
- 内存泄漏:观察者若持有所在 Activity 或 Fragment 的强引用,而被观察者长期存活(如单例服务),就会导致界面无法回收。建议用 WeakReference 包装监听器,或在 onDestroy 时显式 detach
- 并发风险:多个线程可能同时调用 attach/detach/notify。对观察者列表的操作需加锁(如使用 CopyOnWriteArrayList),或保证注册/通知不在同一临界区
- 通知顺序与失败隔离:一个观察者执行异常不应中断其余通知。应在 notify 循环中 try-catch 每个回调,并记录日志,避免雪崩
结合框架已有机制更高效
不必重复造轮子,优先复用成熟抽象:
- Spring 生态直接用 ApplicationEventPublisher + @EventListener,支持异步、事务绑定、条件过滤
- Android 开发可用 LiveData 或 StateFlow,天然支持生命周期感知和主线程分发
- 微服务场景下,可将本地观察者升级为消息中间件订阅(如 Kafka Topic),实现跨进程解耦











