Java 设计模式:观察者模式详解
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会收到通知并自动更新。这种模式广泛用于事件监听和发布-订阅场景。本文将介绍观察者模式的定义、实现方式及其在 Java 中的应用。
1. 什么是观察者模式?
观察者模式的核心思想是:通过建立一个主题(Subject)和多个观察者(Observer)之间的订阅关系,实现状态变化的动态通知。它解耦了主体和观察者,使得系统更灵活、可扩展。
模式结构
- 抽象主题(Subject):维护观察者列表,提供添加、删除和通知观察者的方法。
- 具体主题(Concrete Subject):实现主题接口,状态变化时通知观察者。
- 抽象观察者(Observer):定义更新接口,接收通知后执行操作。
- 具体观察者(Concrete Observer):实现更新方法,响应状态变化。
2. 观察者模式的实现方式
以下是一个简单的示例:模拟一个天气站,天气数据更新时通知多个显示设备。
2.1 定义抽象观察者接口
java
public interface Observer {
void update(float temperature, float humidity); // 更新方法
}
2.2 定义抽象主题接口
java
public interface Subject {
void registerObserver(Observer observer); // 注册观察者
void removeObserver(Observer observer); // 移除观察者
void notifyObservers(); // 通知所有观察者
}
2.3 实现具体主题
java
import java.util.ArrayList;
import java.util.List;
public class WeatherStation implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
public WeatherStation() {
this.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);
}
}
// 更新天气数据并通知观察者
public void setMeasurements(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
notifyObservers();
}
}
2.4 实现具体观察者
java
public class DisplayDevice implements Observer {
private String deviceName;
public DisplayDevice(String deviceName) {
this.deviceName = deviceName;
}
@Override
public void update(float temperature, float humidity) {
System.out.println(deviceName + " 收到更新: 温度 = " + temperature + "°C, 湿度 = " + humidity + "%");
}
}
2.5 客户端使用
java
public class Client {
public static void main(String[] args) {
// 创建主题
WeatherStation weatherStation = new WeatherStation();
// 创建观察者
DisplayDevice display1 = new DisplayDevice("显示屏1");
DisplayDevice display2 = new DisplayDevice("显示屏2");
// 注册观察者
weatherStation.registerObserver(display1);
weatherStation.registerObserver(display2);
// 更新天气数据
weatherStation.setMeasurements(25.5f, 60.0f);
// 移除一个观察者
weatherStation.removeObserver(display1);
// 再次更新
weatherStation.setMeasurements(28.0f, 55.0f);
}
}
输出结果
显示屏1 收到更新: 温度 = 25.5°C, 湿度 = 60.0%
显示屏2 收到更新: 温度 = 25.5°C, 湿度 = 60.0%
显示屏2 收到更新: 温度 = 28.0°C, 湿度 = 55.0%
3. Java 中的内置支持
Java 提供了 java.util.Observable
类和 java.util.Observer
接口,可以直接实现观察者模式。不过,这些类在 Java 9 中已被标记为过时,推荐使用自定义实现或事件监听机制。
示例:使用 Observable
java
import java.util.Observable;
import java.util.Observer;
class WeatherData extends Observable {
private float temperature;
public void setTemperature(float temperature) {
this.temperature = temperature;
setChanged(); // 标记状态变化
notifyObservers(temperature);
}
}
class Display implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("温度更新为: " + arg + "°C");
}
}
public class Client {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Display display = new Display();
weatherData.addObserver(display);
weatherData.setTemperature(26.0f);
}
}
4. 观察者模式的优缺点
优点
- 解耦主体与观察者:主题和观察者之间松耦合,可独立变化。
- 支持广播通信:一个状态变化可通知多个观察者。
- 动态扩展:运行时可增删观察者,灵活性高。
缺点
- 通知开销:观察者过多时,通知过程可能影响性能。
- 内存泄漏风险:未及时移除观察者可能导致引用残留。
- 复杂性增加:大规模系统中管理观察者关系可能变得复杂。
5. 实际应用场景
- GUI 事件监听:如 Swing 或 JavaFX 中的按钮点击事件。
- 发布-订阅系统:如消息队列(Kafka、RabbitMQ)的简化版。
- 状态监控:如天气预报、股票价格更新。
示例:Java 中的 ActionListener
java
button.addActionListener(e -> System.out.println("按钮被点击"));
这里,ActionListener
是观察者,按钮是主题。
6. 与发布-订阅模式的区别
- 观察者模式:主题直接通知观察者,耦合度稍高。
- 发布-订阅模式:通过中间件(如事件总线)解耦,发布者和订阅者无直接联系。
7. 总结
观察者模式是一种强大的行为模式,适用于需要动态响应的场景。通过主题和观察者的解耦设计,它提供了灵活的状态通知机制。在 Java 中,无论是自定义实现还是借助框架(如 Spring 的事件机制),观察者模式都能有效提升系统的可扩展性。
希望这篇博文能帮助你掌握观察者模式的精髓!如果有其他设计模式相关问题,欢迎留言讨论。