观察者模式
观察者模式 (Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知并自动更新。
核心思想:
观察者模式将**观察者(Observer)和被观察者(Subject)**解耦,允许对象独立变化,并且当被观察者状态变化时,自动通知所有观察者。
观察者模式中的角色:
- Subject(被观察者):负责维护观察者列表,并在自身状态发生变化时通知所有观察者。它提供注册、移除和通知观察者的方法。
- Observer(观察者):定义一个接口,用于接收来自被观察者的通知。
- ConcreteSubject(具体被观察者) :实现
Subject
接口,包含具体的状态,并在状态变化时调用notifyObservers()
。 - ConcreteObserver(具体观察者) :实现
Observer
接口,并在被观察者状态变化时更新自身。
观察者模式的 UML 原理类图
类图解释:
- Subject(被观察者接口) :
- 定义了方法
registerObserver()
、removeObserver()
和notifyObservers()
,用于管理观察者的注册、移除和通知操作。
- 定义了方法
- Observer(观察者接口) :
- 定义了
update()
方法,观察者通过该方法接收来自被观察者的更新通知。
- 定义了
- ConcreteSubject(具体被观察者) :
- 维护一个观察者列表,并保存自身的状态。当状态发生变化时,调用
notifyObservers()
方法通知所有观察者。 - 提供了
getState()
和setState()
方法来管理其状态,并在状态更新时调用通知方法。
- 维护一个观察者列表,并保存自身的状态。当状态发生变化时,调用
- ConcreteObserver(具体观察者) :
- 持有对具体被观察者的引用,并实现
update()
方法,在被观察者状态变化时更新自身。
- 持有对具体被观察者的引用,并实现
案例:天气预报系统 ☀️🌧️
场景说明:
假设我们有一个天气预报系统,它实时监控天气数据,并向多个显示设备(如手机、电视、平板等)推送更新信息。系统中,气象站负责监控天气数据,当气温、湿度等信息发生变化时,它会通知所有的显示设备。这些设备会自动更新并显示最新的天气信息。
代码实现
Step 1: 定义 Observer
接口
java
// 观察者接口
public interface Observer {
void update(float temperature, float humidity, float pressure);
}
Step 2: 定义 Subject
接口
java
// 被观察者接口
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
Step 3: 实现具体的 Subject
类
java
import java.util.ArrayList;
import java.util.List;
// 具体的被观察者:天气数据
public 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 setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers(); // 通知观察者
}
}
Step 4: 实现具体的 Observer
类
PhoneDisplay 观察者
java
// 具体观察者:手机显示器
public class PhoneDisplay implements Observer {
private float temperature;
private float humidity;
private float pressure;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("Phone Display - Temp: " + temperature + "°C, Humidity: " + humidity + "%, Pressure: " + pressure + "Pa");
}
}
TVDisplay 观察者
java
// 具体观察者:电视显示器
public class TVDisplay implements Observer {
private float temperature;
private float humidity;
private float pressure;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("TV Display - Temp: " + temperature + "°C, Humidity: " + humidity + "%, Pressure: " + pressure + "Pa");
}
}
Step 5: 测试观察者模式
java
public class ObserverPatternDemo {
public static void main(String[] args) {
// 创建被观察者(天气数据)
WeatherData weatherData = new WeatherData();
// 创建观察者
PhoneDisplay phoneDisplay = new PhoneDisplay();
TVDisplay tvDisplay = new TVDisplay();
// 注册观察者
weatherData.registerObserver(phoneDisplay);
weatherData.registerObserver(tvDisplay);
// 模拟天气数据变化
weatherData.setMeasurements(25.0f, 65.0f, 1013.0f);
weatherData.setMeasurements(28.0f, 70.0f, 1010.0f);
}
}
输出结果:
Phone Display - Temp: 25.0°C, Humidity: 65.0%, Pressure: 1013.0Pa
TV Display - Temp: 25.0°C, Humidity: 65.0%, Pressure: 1013.0Pa
Phone Display - Temp: 28.0°C, Humidity: 70.0%, Pressure: 1010.0Pa
TV Display - Temp: 28.0°C, Humidity: 70.0%, Pressure: 1010.0Pa
Spring Boot 中使用观察者模式
在 Spring Boot 框架中,观察者模式主要可以通过 Spring 的事件驱动机制(Event Driven) 来实现。这是 Spring 框架对观察者模式的原生支持,允许不同的组件之间进行解耦通信,使得事件的发布者和监听者(观察者)可以独立变化。
Spring 事件驱动机制的核心概念:
- 事件(Event):类似于观察者模式中的 "Subject"(被观察者),当事件发生时,发布该事件。
- 事件监听器(Listener):类似于观察者,监听特定的事件并在事件发布时自动响应。
- 事件发布器(Publisher):发布事件,让所有监听器接收事件通知。
如何在 Spring Boot 中实现观察者模式:步骤详解**
Step 1: 创建自定义事件类
自定义事件类需要继承 Spring 提供的 ApplicationEvent
类。事件类可以封装一些需要传递的状态信息。
java
import org.springframework.context.ApplicationEvent;
// 自定义事件类,继承 ApplicationEvent
public class CustomEvent extends ApplicationEvent {
private String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
Step 2: 创建事件监听器
实现 ApplicationListener
接口,或使用注解 @EventListener
来创建监听器。监听器会在事件发布时自动被调用。
java
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
// 事件监听器
@Component
public class CustomEventListener {
// 使用 @EventListener 注解监听自定义事件
@EventListener
public void handleCustomEvent(CustomEvent event) {
System.out.println("Received event - " + event.getMessage());
}
}
Step 3: 创建事件发布器
使用 ApplicationEventPublisher
来发布事件。当需要通知观察者时,可以发布自定义事件。
java
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
// 事件发布器
@Component
public class CustomEventPublisher {
private final ApplicationEventPublisher publisher;
public CustomEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
// 发布事件
public void publishEvent(String message) {
CustomEvent event = new CustomEvent(this, message);
publisher.publishEvent(event); // 发布自定义事件
}
}
Step 4: 使用事件发布器
在 Spring Boot 应用中,通过事件发布器发布事件,触发所有监听该事件的观察者。
java
@RestController
public class BasicController {
@PostMapping("/publish")
void publish(@RequestBody String message){
eventPublisher.publishEvent(message);
}
}
输出结果
java
Received event - {
"message": "hello"
}
Spring 事件驱动机制 VS 传统观察者模式
相似性:
- 解耦 :事件发布者(
ApplicationEventPublisher
)和事件监听器(ApplicationListener
或@EventListener
)之间是解耦的,它们通过事件进行通信。 - 一对多:一个事件可以被多个监听器同时监听,符合观察者模式的一对多依赖关系。
不同点:
- 事件发布是异步的 :Spring 的事件驱动机制允许事件的异步处理(如果配置了
@Async
注解),而传统的观察者模式通常是同步执行的。 - 更加灵活的监听机制 :Spring 提供了基于注解的
@EventListener
,简化了监听器的注册过程,并可以使用条件过滤等高级功能。
在 Spring Boot 中,通过其内置的 事件驱动机制,可以轻松实现观察者模式。这种机制不仅保留了观察者模式的基本思想,还进一步增强了可扩展性和灵活性,支持异步处理、注解配置等高级特性。它在处理系统之间的解耦和事件驱动编程时尤其强大,非常适合使用在实际项目中。
使用观察者模式的典型场景:
- 异步事件通知:如用户注册、邮件发送等需要异步处理的操作。
- 解耦组件间的通信:模块化应用中,各模块之间的消息传递和事件处理。
总结
观察者模式 提供了一种解耦对象之间的依赖关系的方式,使得被观察者和观察者可以在不直接相互依赖的情况下进行通信。通过观察者模式,当一个对象发生变化时,所有依赖于它的对象都会自动收到通知并作出相应的处理。