观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系。一个对象(称为主题)状态发生变化时,所有依赖于它的对象(称为观察者)都会自动得到通知并更新。这样,观察者与主题之间是松耦合的,观察者只关心是否需要接收通知,而不需要关心主题的具体实现。
观察者模式常见的应用场景包括事件处理系统、消息推送系统、订阅/发布系统等。
观察者模式的主要角色包括:
+-----------------------+ +----------------------+
| Subject |<--------+ | Observer |
|-----------------------| | |----------------------|
| - observers | | | + update() |
| + attach(observer) | | +----------------------+
| + detach(observer) | |
| + notify() | |
+-----------------------+ |
| |
v v
+-------------------------+ +----------------------------+
| ConcreteSubject | | ConcreteObserver |
|-------------------------| |----------------------------|
| - state | | - observerState |
| + getState() | | + update() |
| + setState(state) | | |
+-------------------------+ +----------------------------+update() 方法,用来在主题状态变化时执行更新操作。
Subject 的具体实现,维护状态并提供接口修改状态。每当状态发生变化时,它会通知所有注册的观察者。
Observer 的具体实现,负责接收状态更新并执行具体的操作。
我们通过一个实际的例子来展示如何实现观察者模式。假设我们有一个天气监测系统,主题是天气,观察者是显示设备(例如温度显示器、湿度显示器等)。
// 观察者接口
interface Observer {
void update(String temperature, String humidity);
}
// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
// 具体观察者:温度显示器
class TemperatureDisplay implements Observer {
private String temperature;
@Override
public void update(String temperature, String humidity) {
this.temperature = temperature;
display();
}
public void display() {
System.out.println("Temperature Display: " + temperature);
}
}
// 具体观察者:湿度显示器
class HumidityDisplay implements Observer {
private String humidity;
@Override
public void update(String temperature, String humidity) {
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Humidity Display: " + humidity);
}
}
// 具体主题:天气站
class WeatherStation implements Subject {
private String temperature;
private String humidity;
private List<Observer> observers = new ArrayList<>();
public void setWeatherData(String temperature, String humidity) {
this.temperature = temperature;
this.humidity = humidity;
notifyObservers(); // 状态变化,通知所有观察者
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity);
}
}
}
public class ObserverPatternDemo {
public static void main(String[] args) {
// 创建具体主题
WeatherStation weatherStation = new WeatherStation();
// 创建具体观察者
TemperatureDisplay tempDisplay = new TemperatureDisplay();
HumidityDisplay humidityDisplay = new HumidityDisplay();
// 注册观察者
weatherStation.attach(tempDisplay);
weatherStation.attach(humidityDisplay);
// 设置天气数据,所有观察者会收到通知
weatherStation.setWeatherData("30°C", "60%");
weatherStation.setWeatherData("25°C", "50%");
}
}update() 方法,所有的具体观察者都必须实现该方法,以便在主题发生变化时,能够接收到更新信息。
attach()、detach() 和 notifyObservers() 方法。attach() 方法用来注册观察者,detach() 用来注销观察者,notifyObservers() 在主题状态变化时通知所有观察者。
Subject 的具体实现,维护温度和湿度两个状态,并在状态变化时通知所有注册的观察者。
Observer 的实现,它们通过 update() 方法接收主题的状态变化,并执行更新操作(例如显示新温度或湿度)。
ObserverPatternDemo 中,我们创建了一个 WeatherStation 对象,注册了两个观察者(温度显示器和湿度显示器),并模拟了天气数据的变化。
Temperature Display: 30°C
Humidity Display: 60%
Temperature Display: 25°C
Humidity Display: 50%观察者模式在许多实际应用中都非常有用,尤其是那些需要实现"一对多"依赖关系的场景。以下是一些常见的应用场景:
观察者模式是一个非常实用的设计模式,特别适用于那些需要实时通知相关对象的场景,如事件驱动的程序、实时数据推送、GUI事件监听等。通过观察者模式,系统中的各个组件之间能够保持松耦合,方便扩展和维护。然而,使用时要注意其带来的性能开销,特别是在观察者数量非常多或更新频繁的情况下。为了避免性能问题和复杂性,通常需要做好合理的优化和管理策略。通过观察者模式,我们可以实现高效的事件处理和状态同步,使得对象间的交互更加清晰、灵活且易于管理。
如果您有任何问题或建议,欢迎留言讨论。