观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象的状态变化。当主题对象的状态发生变化时,它会通知所有注册的观察者对象,使得观察者对象能够自动更新自己。
观察者模式主要包含以下几个角色:
- 主题(Subject):被观察的对象,维护一组观察者,并提供添加、删除观察者以及通知观察者的方法。
- 观察者(Observer):定义了一个更新接口,用于在主题状态发生变化时接收通知。
- 具体主题(ConcreteSubject):具体的被观察对象,实现主题接口,维护了一个观察者列表,并在状态变化时通知观察者。
- 具体观察者(ConcreteObserver):具体的观察者对象,实现观察者接口,当接收到主题通知时,执行相应的更新操作。
观察者模式可以实现松耦合的设计,主题和观察者之间的依赖关系降低了耦合度,使得主题和观察者可以独立地进行扩展和变化。
示例:
假设我们有一个气象站程序,其中包含一个气象数据主题(WeatherDataSubject)和两个观察者(CurrentConditionsDisplay、StatisticsDisplay),这两个观察者用于显示不同的气象数据。
package com.example.demo.guanchazhe;
import java.util.ArrayList;
import java.util.List;
// 主题:气象数据
interface WeatherDataSubject {
void registerObserver(WeatherDataObserver observer);
void removeObserver(WeatherDataObserver observer);
void notifyObservers();
void setMeasurements(float temperature, float humidity, float pressure);
}
// 观察者:气象数据显示
interface WeatherDataObserver {
void update(float temperature, float humidity, float pressure);
}
// 具体主题:气象数据
class WeatherData implements WeatherDataSubject {
private List<WeatherDataObserver> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(WeatherDataObserver observer) {
observers.add(observer);
}
@Override
public void removeObserver(WeatherDataObserver observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (WeatherDataObserver observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
private void measurementsChanged() {
notifyObservers();
}
}
// 具体观察者:当前气象数据显示
class CurrentConditionsDisplay implements WeatherDataObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.println("当前气象数据:温度 " + temperature + "°C, 湿度 " + humidity + "%, 气压 " + pressure + " hPa");
}
}
// 具体观察者:气象数据统计显示
class StatisticsDisplay implements WeatherDataObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
// 这里可以实现气象数据的统计分析和显示
System.out.println("气象数据统计显示:统计分析中...");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
WeatherDataSubject weatherData = new WeatherData();
WeatherDataObserver currentDisplay = new CurrentConditionsDisplay();
WeatherDataObserver statisticsDisplay = new StatisticsDisplay();
weatherData.registerObserver(currentDisplay);
weatherData.registerObserver(statisticsDisplay);
// 模拟气象数据变化
weatherData.setMeasurements(25.5f, 65f, 1013.2f);
}
}
在上面的示例中,我们定义了主题接口WeatherDataSubject
和观察者接口WeatherDataObserver
。然后,实现了一个具体主题类WeatherData
,它维护了一个观察者列表,并在气象数据变化时通知所有注册的观察者。还实现了两个具体观察者类CurrentConditionsDisplay
和StatisticsDisplay
,它们分别用于显示当前气象数据和进行气象数据统计。
通过观察者模式,我们可以实现主题和观察者之间的解耦,使得主题和观察者可以独立地进行扩展和变化。当气象数据发生变化时,具体主题会通知所有注册的观察者,观察者会自动更新自己的显示内容。这样可以方便地添加新的观察者来显示不同的气象数据,而不需要修改主题的代码。