观察者模式(Observer Pattern)学习笔记
编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793
DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039
1. 模式定义
行为型设计模式,定义对象间的一种一对多依赖关系,当一个对象状态发生改变时,所有依赖它的对象都会得到通知并自动更新。又称为发布-订阅模式。
2. 适用场景
✅ 需要实现事件触发机制
✅ 存在多个对象依赖一个对象状态的场景
✅ 需要实现广播通信机制
✅ 需要解耦观察者与被观察者
✅ 需要动态增减观察者对象
3. 模式结构
4. 核心角色
角色 | 说明 |
---|---|
Subject | 抽象主题(被观察者),定义注册、删除、通知观察者的接口 |
ConcreteSubject | 具体主题,维护观察者列表,状态改变时通知所有观察者 |
Observer | 抽象观察者,定义更新接口 |
ConcreteObserver | 具体观察者,实现更新逻辑 |
5. 代码示例
5.1 气象站监控示例
// 抽象主题
interface WeatherSubject {
void registerObserver(WeatherObserver o);
void removeObserver(WeatherObserver o);
void notifyObservers();
}
// 具体主题
class WeatherStation implements WeatherSubject {
private List<WeatherObserver> observers = new ArrayList<>();
private float temperature;
private float humidity;
public void setMeasurements(float temp, float humidity) {
this.temperature = temp;
this.humidity = humidity;
notifyObservers();
}
public void registerObserver(WeatherObserver o) {
observers.add(o);
}
public void removeObserver(WeatherObserver o) {
observers.remove(o);
}
public void notifyObservers() {
for (WeatherObserver o : observers) {
o.update(temperature, humidity);
}
}
}
// 抽象观察者
interface WeatherObserver {
void update(float temp, float humidity);
}
// 具体观察者
class CurrentConditionsDisplay implements WeatherObserver {
public void update(float temp, float humidity) {
System.out.printf("当前天气状况:温度%.1f℃ 湿度%.1f%%\n", temp, humidity);
}
}
class StatisticsDisplay implements WeatherObserver {
public void update(float temp, float humidity) {
// 实现统计逻辑
System.out.println("更新统计数据显示...");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
WeatherStation station = new WeatherStation();
WeatherObserver currentDisplay = new CurrentConditionsDisplay();
WeatherObserver statisticsDisplay = new StatisticsDisplay();
station.registerObserver(currentDisplay);
station.registerObserver(statisticsDisplay);
station.setMeasurements(25.5f, 65.0f);
/* 输出:
当前天气状况:温度25.5℃ 湿度65.0%
更新统计数据显示... */
}
}
6. 模式变种
6.1 推拉模型对比
模型类型 | 数据传递方式 | 特点 |
---|---|---|
推 | 主题主动发送完整数据给观察者 | 观察者被动接收,可能收到不需要的数据 |
拉 | 观察者主动从主题获取所需数据 | 需要时获取,减少不必要数据传输 |
// 拉模型实现示例
interface PullObserver {
void update(WeatherSubject subject);
}
class PullWeatherDisplay implements PullObserver {
public void update(WeatherSubject subject) {
if (subject instanceof WeatherStation) {
WeatherStation ws = (WeatherStation)subject;
System.out.println("温度:" + ws.getTemperature());
}
}
}
7. 优缺点分析
✔️ 优点:
- 实现松耦合
- 支持动态添加/删除观察者
- 符合开闭原则
- 支持广播通信
❌ 缺点:
- 通知顺序不可控
- 观察者过多时影响性能
- 循环依赖可能导致系统崩溃
- 观察者可能收到不相关通知
8. 相关模式对比
模式 | 目的 | 关键区别 |
---|---|---|
发布-订阅模式 | 消息通知机制 | 通过消息代理解耦,支持更复杂路由 |
中介者模式 | 对象间交互 | 集中控制通信,观察者模式是分布式通知 |
责任链模式 | 请求传递 | 观察者模式是单向通知机制 |
9. 实际应用案例
- Java Swing的事件监听机制(
ActionListener
) - Spring框架的
ApplicationEvent
和ApplicationListener
- Android的
BroadcastReceiver
- JavaBeans的
PropertyChangeListener
- Reactor编程模型
- Vue.js的响应式系统
- Kafka消息队列
10. 最佳实践建议
- 使用Java内置实现:
// Java 9之前可用(已过时)
import java.util.Observable;
import java.util.Observer;
// Java 9+推荐使用PropertyChangeSupport
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
- 防止内存泄漏:
// 及时移除观察者
subject.addObserver(observer);
// ...
subject.deleteObserver(observer);
- 异步通知优化:
// 使用线程池异步通知
ExecutorService executor = Executors.newCachedThreadPool();
public void notifyObservers() {
for (Observer o : observers) {
executor.submit(() -> o.update(data));
}
}
- 使用弱引用(WeakReference):
// 防止观察者无法被垃圾回收
List<WeakReference<Observer>> weakObservers = new ArrayList<>();
public void registerObserver(Observer o) {
weakObservers.add(new WeakReference<>(o));
}
- 事件过滤机制:
// 添加事件类型过滤
interface EventObserver {
void update(EventType type, Object data);
}
enum EventType { TEMP_CHANGE, HUMIDITY_CHANGE }
11. 扩展应用(Spring事件机制)
// 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
// getter...
}
// 事件发布者
@Service
class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 创建订单逻辑...
publisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
// 事件监听者
@Component
class NotificationService {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// 发送通知逻辑...
}
}
🔍 设计原则体现:
- 开闭原则(OCP):新增观察者无需修改主题
- 松耦合原则:主题与观察者互相不知道对方细节
- 单一职责原则:主题管理状态,观察者处理通知
通过观察者模式,可以实现高效的事件通知机制,特别适合需要实现实时数据同步、事件驱动架构的场景。该模式在GUI开发、分布式系统和框架设计中应用广泛,是解耦组件关系的经典解决方案。