1. 观察者模式的定义
观察者模式 (Observer Pattern)是一种行为设计模式 ,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式所做的工作就是在解除耦合。使耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
观察者模式解决了以下关键问题:
- 状态同步难题:当多个对象需要同步状态时,避免硬编码的依赖关系
- 动态订阅机制:运行时动态添加/移除观察者的能力
- 事件驱动架构:构建响应式系统的基石
2. 观察者模式的结构

- Subject:抽象主题,一般为抽象类或接口,将所有的观察者引用存在一个集合里,并提供了增加和删除观察者对象的接口。
java
public abstract class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void setState(String state) {
this.state = state;
notifyObservers(); // 状态变更时通知观察者
}
public String getSubjectState(){
return subjectState;
}
//添加观察者
public void attach(Observer observer) {
observers.add(observer);
}
//删除观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//通知所有观察者
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
- ConcreteSubject:具体主题,将有关联状态存入具体观察者对象。在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
java
public class ConcreteSubject extends Subject {
}
- Observer:抽象观察者,一般为抽象类或接口,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
java
public interface Observer {
void update();
}
- ConcreteObserver:具体观察者,实现具体观察者所要求的更新接口,以便使本身的状态与主题的状态相协调。
java
public class ConcreteObserver implements Observer {
private String name;
private String subjectState;
private Subject subject;
public ConcreteObserver(String name, ConcreteSubject subject) {
this.name = name;
this.subject = subject;
}
@Override
public void update() {
subjectState = subject.getSubjectState();
System.out.println("ConcreteObserver", "Observer " + name + ", state " + subjectState);
}
}
- 客户端代码
java
Subject subject = new ConcreteSubject();
subject.attach(new ConcreteObserver("Zhang San", subject));
subject.attach(new ConcreteObserver("Li Si", subject));
subject.attach(new ConcreteObserver("Wang Wu", subject));
subject.setSubjectState("Change");

3. 观察者模式 Java 内置接口的实现
Java 已经为观察者模式准备好了相关的接口和抽象类了。
java
// 继承Observable类
class WeatherStation extends Observable {
private float temperature;
public void setTemperature(float temp) {
this.temperature = temp;
setChanged(); // 标记状态已改变
notifyObservers(); // 通知观察者
}
}
// 实现Observer接口
class PhoneDisplay implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherStation) {
System.out.println("");
}
}
}
// 使用示例
WeatherStation station = new WeatherStation();
station.addObserver(new PhoneDisplay());
station.setTemperature(25.5f);
4. 观察者模式的优缺点
优点 :
- 解耦设计:主题和观察者之间保持最小依赖
- 动态扩展:无需修改主题即可增加新观察者
- 事件驱动:支持分布式事件处理系统
- 重用性高:主题和观察者可以独立复用
缺点 :
- 通知顺序不可控:观察者接收通知的顺序不确定
- 性能问题:大量观察者可能导致通知过程耗时
- 循环依赖风险:不当实现可能导致循环调用
5. 观察者模式的相关实践
5.1 推拉模型
- 推模型:主题主动将详细数据发送给观察者
- 拉模型:观察者收到通知后主动从主题获取数据
java
// 推模型实现
protected void notifyObservers(Object data) {
for (Observer o : observers) {
o.update(data); // 直接传递数据
}
}
// 拉模型实现(推荐)
protected void notifyObservers() {
for (Observer o : observers) {
o.update(this); // 传递主题引用
}
}
5.2 异步通知机制
线程安全优化,避免阻塞主题线程:
java
public class ConcurrentSubject {
private final CopyOnWriteArrayList<Observer> observers =
new CopyOnWriteArrayList<>();
public void notifyObservers() {
for (Observer o : observers) {
// 使用线程池异步处理
executorService.submit(() -> o.update(this));
}
}
}