观察者模式是一种行为型设计模式,其核心思想是定义 “一对多” 的依赖关系:当一个对象(称为 “主题 / 被观察者”)的状态发生变化时,所有依赖于它的对象(称为 “观察者”)会自动收到通知并进行更新。
该模式的本质是 “解耦主题与观察者” —— 主题无需知道具体有哪些观察者,只需维护一个观察者列表;观察者也无需了解主题的内部逻辑,只需在收到通知时执行自身的更新逻辑,符合 “开闭原则”。

下面我将用 Java 代码实现观察者模式,以气象站系统为例,展示当气象数据变化时,多个显示器如何自动更新显示内容。
首先,我们要定义一个抽象主题接口,它的作用是注册、移除和通知观察者。
1 2 3 4 5 6 7 8 9 10 11 12
| public interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); }
|
具体的主题,也就是被观察者要实现Subject接口。它会维护气象数据和观察者列表。当数据更新时,会通知所有的注册者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| import java.util.ArrayList; import java.util.List;
public class WeatherData implements Subject { private double temperature; private double humidity; private List<Observer> observers; public WeatherData() { observers = new ArrayList<>(); } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(); } } public void setWeatherData(double temperature, double humidity) { this.temperature = temperature; this.humidity = humidity; notifyObservers(); } public double getTemperature() { return temperature; } public double getHumidity() { return humidity; } }
|
我们还需要定义观察者的抽象接口,所有的具体观察者都要继承它,这个接口定义了更新丰富,也就是当被观察者对象发送变化时通过这个来通知观察者
1 2 3 4 5 6
| public interface Observer { void update(); }
|
有了接口抽象,接下来定义具体的观察者,这里我们定义了温度和湿度的观察者,当气候发送变化时他们会收到通知并获取气候数据来显示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class HumidityDisplay implements Observer { private WeatherData weatherData; public HumidityDisplay(WeatherData weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update() { double humidity = weatherData.getHumidity(); display(humidity); } private void display(double humidity) { System.out.println("湿度显示器: 当前湿度为 " + humidity + " %"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class TemperatureDisplay implements Observer { private WeatherData weatherData; public TemperatureDisplay(WeatherData weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update() { double temperature = weatherData.getTemperature(); display(temperature); } private void display(double temperature) { System.out.println("温度显示器: 当前温度为 " + temperature + " °C"); } }
|
最后通过客户端代码来演示它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Client { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); new TemperatureDisplay(weatherData); new HumidityDisplay(weatherData); System.out.println("--- 第一次更新气象数据 ---"); weatherData.setWeatherData(25.5, 60.0); System.out.println("\n--- 第二次更新气象数据 ---"); weatherData.setWeatherData(26.3, 58.5); System.out.println("\n--- 第三次更新气象数据 ---"); weatherData.setWeatherData(24.8, 62.3); } }
|
从上面的代码可以看出:
- 客户端创建具体主题(WeatherData)实例
- 创建具体观察者(TemperatureDisplay、HumidityDisplay)时,观察者会自动注册到主题
- 当主题的状态(气象数据)发生变化时:
- 调用主题的 setWeatherData () 方法更新数据
- 主题内部调用 notifyObservers () 方法通知所有观察者
- 每个观察者的 update () 方法被调用
- 观察者从主题拉取最新数据并更新显示
这种设计模式的优势在于:
- 主题和观察者之间实现了解耦,彼此不需要知道对方的具体实现
- 可以方便地添加新的观察者,无需修改主题代码
- 当主题状态变化时,所有相关观察者会自动收到通知并更新
- 符合开闭原则,系统扩展性好