简介:
观察者模式是一种行为设计模式,它允许对象(称为观察者)订阅另一个对象(称为主题)的状态变化。当主题状态发生改变时,观察者会被通知并进行相应的更新。
在现实生活中,我们经常会遇到这样的情况:当一个对象的状态发生改变时,其他对象也需要做出相应的变化。观察者模式提供了一种松耦合的方式来实现这种通信机制,使得主题和观察者之间的依赖关系更加灵活。
观察者模式的 UML 类图如下所示:
+-------------+ +----------------+
| Subject | -----> | Observer |
+-------------+ +----------------+
| + attach(o) | | + update() |
| + detach(o) | +----------------+
| + notify() |
+-------------+假设我们有一个简单的气象站应用,气象站会定期测量温度、湿度和气压。我们希望当气象数据发生变化时,能够实时地通知给注册的观察者。
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
// 注册观察者
void registerObserver(Observer observer);
// 移除观察者
void removeObserver(Observer observer);
// 通知所有观察者
void notifyObservers();
}
// 观察者接口
interface Observer {
// 更新观察者状态
void update(float temperature, float humidity, float pressure);
}
// 具体主题类
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
// 构造函数
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(temperature, humidity, pressure);
}
}
// 当气象数据发生变化时调用该方法
public void measurementsChanged() {
notifyObservers();
}
// 设置气象数据
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
// 数据变化后通知观察者
measurementsChanged();
}
}
// 具体观察者类
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
@Override
public void update(float temperature, float humidity, float pressure) {
// 更新观察者状态
this.temperature = temperature;
this.humidity = humidity;
// 显示当前气象数据
display();
}
// 显示当前气象数据
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
public class WeatherStation {
public static void main(String[] args) {
// 创建主题对象
WeatherData weatherData = new WeatherData();
// 创建观察者对象
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
// 注册观察者到主题对象
weatherData.registerObserver(currentDisplay);
// 模拟气象数据变化
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}这段代码实现了一个简单的气象站应用。WeatherData 类是主题,它维护了观察者列表,并提供了方法来注册、移除和通知观察者。CurrentConditionsDisplay 类是具体的观察者,它实现了 Observer 接口,并在更新时显示当前的气象数据。
在 main 方法中,我们创建了一个 WeatherData 对象和一个 CurrentConditionsDisplay 对象,并将后者注册为前者的观察者。然后,我们模拟了几次气象数据的变化,并观察观察者的更新情况。
Current conditions: 80.0F degrees and 65.0% humidity
Current conditions: 82.0F degrees and 70.0% humidity
Current conditions: 78.0F degrees and 90.0% humidity这个结果显示了每次调用 setMeasurements() 方法后,CurrentConditionsDisplay 观察者都会接收到通知,并且显示当前的气象条件(温度和湿度)。
在 main 方法中,创建了一个 WeatherData 对象和一个 CurrentConditionsDisplay 对象,并将后者注册为前者的观察者。然后,模拟了几次气象数据的变化,并观察观察者的更新情况。
在图形用户界面(GUI)开发中,观察者模式被广泛应用。例如,按钮、复选框、滚动条等 GUI 组件可以作为主题,而窗口、文本框等可以作为观察者。当用户与 GUI 组件进行交互时,观察者会接收到通知并执行相应的操作,从而实现 GUI 的实时更新和交互。
股票市场监控系统需要实时监测股票价格的变化,并及时通知相关的投资者或交易员。股票价格变化可以作为主题,而投资者或交易员可以作为观察者。当股票价格发生变化时,观察者会收到通知并做出相应的交易决策。
在车辆追踪系统中,车辆的位置和状态需要实时监测,并及时通知相关的监控中心或用户。车辆的位置和状态可以作为主题,而监控中心或用户可以作为观察者。当车辆的位置或状态发生变化时,观察者会收到通知并进行相应的处理。
观察者模式与事件驱动编程密切相关。在事件驱动编程中,事件是主题,而事件处理程序则是观察者。当事件发生时,观察者会收到通知并执行相应的处理逻辑,从而实现程序的事件驱动和响应机制。