观察者模式是一种行为设计模式,其中一个对象(称为主题)维护其依赖项(称为观察者)的列表,当主题的状态发生变化时,它通知所有的观察者,使得它们能够自动更新。
观察者模式主要涉及三个角色:
主题(Subject): 维护一组观察者,提供方法来添加和删除观察者,以及通知观察者状态变化的方法。
观察者(Observer): 定义一个更新接口,以便主题在状态变化时能够通知观察者。
具体主题(ConcreteSubject): 继承自主题,实现具体的业务逻辑,并在状态发生变化时通知观察者。
具体观察者(ConcreteObserver): 实现观察者接口,以便在接收到通知时能够执行相应的操作。
结构图
场景
假设我们有一个气象站,气象站会定期更新温度,湿度和气压。我们希望设计一个系统,当气象站的数据更新时,所有注册的显示器(观察者)都能够自动更新显示。
代码
// 主题接口:气象站
interface WeatherStation {
void registerObserver(WeatherObserver observer);
void removeObserver(WeatherObserver observer);
void notifyObservers();
}
// 观察者接口:显示器
interface WeatherObserver {
void update(float temperature, float humidity, float pressure);
}
// 具体主题:具体的气象站
class ConcreteWeatherStation implements WeatherStation {
private List<WeatherObserver> observers;
private float temperature;
private float humidity;
private float pressure;
public ConcreteWeatherStation() {
this.observers = new ArrayList<>();
}
@Override
public void registerObserver(WeatherObserver observer) {
observers.add(observer);
}
@Override
public void removeObserver(WeatherObserver observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (WeatherObserver observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 模拟气象站数据更新
public void setWeatherData(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();
}
}
// 具体观察者1:温度显示器
class TemperatureDisplay implements WeatherObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.println("Temperature Display: Current Temperature = " + temperature);
}
}
// 具体观察者2:湿度显示器
class HumidityDisplay implements WeatherObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.println("Humidity Display: Current Humidity = " + humidity);
}
}
// 客户端
public class ObserverPatternExample {
public static void main(String[] args) {
ConcreteWeatherStation weatherStation = new ConcreteWeatherStation();
// 注册观察者
WeatherObserver temperatureDisplay = new TemperatureDisplay();
WeatherObserver humidityDisplay = new HumidityDisplay();
weatherStation.registerObserver(temperatureDisplay);
weatherStation.registerObserver(humidityDisplay);
// 模拟气象站数据更新,观察者自动更新显示
weatherStation.setWeatherData(25.5f, 60.0f, 1012.0f);
// 移除一个观察者
weatherStation.removeObserver(temperatureDisplay);
// 模拟气象站数据更新,仅湿度显示器会更新
weatherStation.setWeatherData(26.0f, 65.0f, 1010.5f);
}
}
在客户端,我们创建了一个具体的气象站对象,并注册了温度显示器和湿度显示器作为观察者。随后,通过模拟气象站数据的更新,观察者自动更新了显示
优点
松耦合: 观察者模式实现了目标和观察者之间的松耦合。主题(目标)和观察者之间相互独立,它们只是通过接口进行通信。
可扩展性: 新的观察者可以随时被加入到系统中,而无需修改主题的代码。这使得系统更容易扩展和维护。
通知机制: 主题发生变化时,会自动通知所有的观察者。这种通知机制使得观察者能够实时获取目标的最新状态。
缺点
可能引起性能问题: 如果观察者非常多,而且通知频繁,可能会影响性能。因为每个观察者都需要被通知,而且通知是同步的。
可能导致循环依赖: 当观察者之间存在相互依赖时,可能导致循环依赖的问题。这样的情况下,系统可能需要被重新设计。
可能造成内存泄漏: 如果观察者没有被正确地移除,可能导致对观察者的引用一直存在,造成内存泄漏。