《观察者模式》|设计模式系列第23篇
系列:行为型模式 · 观察者模式(Observer Pattern)
关键词:发布订阅、一对多联动、主题、观察者、事件通知、松耦合
一、什么是观察者模式
观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
属于行为型设计模式。

简单理解:
主题(Subject)内部维护一组观察者列表。当主题状态发生变化,自动广播消息通知所有已注册观察者;观察者收到通知后执行自己的更新逻辑。观察者只订阅主题,主题只知道观察者统一接口,双方松耦合。
例子:新闻订阅,报社(主题)发布新闻,所有订阅读者(观察者)收到推送;前端事件监听、消息通知。
核心意图
建立一对多依赖;主题状态变更,自动通知所有订阅观察者。
适用场景
- 一个对象状态变化,其他多个对象需要同步响应
- 事件监听、消息推送、数据变更通知
- 广播通知场景,订阅者动态增减
- MVC 模型,Model变更通知View更新
⚠️ 缺点预警:通知是顺序同步执行,观察者过多会阻塞;循环依赖会触发死循环;无法知道通知是否成功处理。
二、UML结构图
角色划分:
- Subject(抽象主题):提供注册、移除观察者、通知接口
- ConcreteSubject(具体主题):保存状态,状态变更时触发通知
- Observer(抽象观察者):定义update通知回调接口
- ConcreteObserver(具体观察者):实现update方法,收到通知执行业务
- Client(客户端):创建主题与观察者,完成订阅

三、Java 完整示例
场景:WeatherStation 气象站(主题),推送温度信息;Display 显示屏观察者。代码全部使用英文。
import java.util.ArrayList;
import java.util.List;
// Observer
public interface Observer {
void update(float temperature);
}
// Subject
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// ConcreteSubject
public class WeatherStation implements Subject {
private List<Observer> observerList = new ArrayList<>();
private float temperature;
public void setTemperature(float temperature) {
this.temperature = temperature;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update(temperature);
}
}
}
// ConcreteObserver
public class CurrentDisplay implements Observer {
@Override
public void update(float temperature) {
System.out.println("CurrentDisplay: temperature = " + temperature);
}
}
public class StatDisplay implements Observer {
@Override
public void update(float temperature) {
System.out.println("StatDisplay: temperature = " + temperature);
}
}
// Client
public class Client {
public static void main(String[] args) {
Subject weatherStation = new WeatherStation();
Observer currentDisplay = new CurrentDisplay();
Observer statDisplay = new StatDisplay();
weatherStation.registerObserver(currentDisplay);
weatherStation.registerObserver(statDisplay);
((WeatherStation) weatherStation).setTemperature(25.6f);
weatherStation.removeObserver(statDisplay);
((WeatherStation) weatherStation).setTemperature(28.1f);
}
}
运行输出:
CurrentDisplay: temperature = 25.6
StatDisplay: temperature = 25.6
CurrentDisplay: temperature = 28.1
四、观察者模式 vs 中介者模式
| 模式 | 目标 | 核心 |
|---|---|---|
| Observer | 一对多单向广播,主题推送消息给订阅者 | 主题发布,观察者被动接收,观察者之间互不感知 |
| Mediator | 多对多双向交互,全部由中介转发 | 多个同事通过中介通信,同事之间无直接引用 |
五、优缺点总结
✅ 优点
- 主题与观察者松耦合,只依赖抽象接口
- 动态新增/删除观察者,运行时订阅取消订阅
- 符合开闭原则,新增观察者不修改主题代码
❌ 缺点
- 默认同步通知,观察者耗时会阻塞主线程
- 没有消息持久化,未订阅的观察者收不到历史消息
- 存在循环调用风险
六、框架源码应用
- JDK
java.util.Observer(已废弃)、java.util.EventListener - Spring ApplicationEvent 事件监听
- Guava EventBus
- RxJava 响应式流(思想同源)
七、小结
观察者模式核心:主题维护观察者列表;状态变更,自动调用所有观察者update方法推送消息。
开发中优先使用框架事件机制(Spring Event / Guava EventBus),很少手写原生观察者;适合事件广播、数据变更通知场景。
0 条笔记