20.设计模式-OBSERVER(观察者)
一、模式定义与核心思想
观察者模式是一种行为型设计模式,其核心目标是建立对象间一对多的依赖关系,使得当目标对象(Subject)状态变化时,所有依赖它的观察者(Observer)都能自动接收通知并更新自身状态。
核心价值:
- 解耦对象关系:将观察者与被观察者解耦,避免直接依赖(如GUI界面与数据模型的分离)。
- 动态扩展性:支持运行时动态添加/移除观察者(如电商系统中新增促销通知渠道)。
- 状态同步机制:确保多个对象状态的一致性(如Excel表格与图表联动更新)。
典型应用场景:
- 用户界面组件的事件响应(如按钮点击触发多个控件更新)
- 分布式系统的消息发布/订阅(如Kafka消息队列)
- 游戏引擎的角色状态同步(如玩家位置变化触发怪物AI响应)
二、模式组成与UML类图
核心角色
- Subject(抽象目标):
-
- 维护观察者集合,提供注册(
attach()
)、注销(detach()
)和通知(notify()
)的接口。
- 维护观察者集合,提供注册(
- ConcreteSubject(具体目标):
-
- 存储具体业务状态(如温度传感器数据),状态变化时触发通知。
- Observer(抽象观察者):
-
- 定义更新接口
update()
,用于接收目标状态变更通知。
- 定义更新接口
- ConcreteObserver(具体观察者):
-
- 实现业务响应逻辑(如更新UI界面、发送短信通知)。
UML类图
classDiagram
class Subject {
<<interface>>
+attach(Observer)
+detach(Observer)
+notify()
}
class ConcreteSubject {
-state: int
+getState()
+setState(int)
}
class Observer {
<<interface>>
+update()
}
class ConcreteObserverA {
-subject: Subject
+update()
}
class ConcreteObserverB {
-subject: Subject
+update()
}
Subject <|-- ConcreteSubject
Observer <|-- ConcreteObserverA
Observer <|-- ConcreteObserverB
ConcreteSubject --> Observer : notifies
ConcreteObserverA --> ConcreteSubject : observes
三、代码实现示例
场景:实现气象站数据变化通知多个显示设备
1. 抽象目标与观察者
// 抽象目标
interface WeatherSubject {
void registerObserver(WeatherObserver o);
void removeObserver(WeatherObserver o);
void notifyObservers();
}
// 抽象观察者
interface WeatherObserver {
void update(float temp, float humidity);
}
2. 具体目标实现
class WeatherStation implements WeatherSubject {
private List<WeatherObserver> observers = new ArrayList<>();
private float temperature;
private float humidity;
@Override
public void registerObserver(WeatherObserver o) {
observers.add(o);
}
@Override
public void removeObserver(WeatherObserver o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (WeatherObserver o : observers) {
o.update(temperature, humidity);
}
}
public void setMeasurements(float temp, float humidity) {
this.temperature = temp;
this.humidity = humidity;
notifyObservers();
}
}
3. 具体观察者实现
class PhoneDisplay implements WeatherObserver {
@Override
public void update(float temp, float humidity) {
System.out.printf("手机端更新: 温度%.1f℃ 湿度%.1f%%\n", temp, humidity);
}
}
class WebDashboard implements WeatherObserver {
@Override
public void update(float temp, float humidity) {
System.out.printf("网页端更新: 温度%.1f℃ 湿度%.1f%%\n", temp, humidity);
}
}
4. 客户端调用
public class Client {
public static void main(String[] args) {
WeatherStation station = new WeatherStation();
WeatherObserver phone = new PhoneDisplay();
WeatherObserver web = new WebDashboard();
station.registerObserver(phone);
station.registerObserver(web);
station.setMeasurements(25.5f, 65); // 触发双端通知
station.removeObserver(web);
station.setMeasurements(26.0f, 60); // 仅手机端更新
}
}
四、工业级源码应用
- Java内置支持:
-
java.util.Observable
类与Observer
接口(已废弃,但广泛用于早期Swing组件)PropertyChangeListener
在JavaBean中的状态监听实现
- Spring框架:
-
ApplicationEvent
与ApplicationListener
实现事件驱动架构@EventListener
注解简化观察者注册(如订单支付成功触发库存扣减)
- Android开发:
-
LiveData
组件通过观察者模式实现数据与UI的自动同步OnClickListener
等事件监听器机制
- GUI工具包:
-
- JavaFX的
InvalidationListener
(如表格数据变更触发图表重绘) - Qt框架的Signal/Slot机制(跨线程事件通知)
- JavaFX的
- 分布式系统:
-
- Redis的发布/订阅(Pub/Sub)消息模式
- ZooKeeper的Watcher机制(节点变化通知)
五、模式优劣与最佳实践
优势:
- 松耦合架构:目标与观察者仅通过抽象接口交互,符合开闭原则
- 实时响应能力:毫秒级状态同步(如股票行情实时刷新)
局限性:
- 通知顺序不可控:多个观察者的执行顺序可能影响系统行为
- 循环触发风险:观察者修改目标状态可能引发无限循环
最佳实践:
- 异步通知优化:结合线程池处理高并发场景(如电商大促期间订单通知)
- 状态过滤机制:仅在关键状态变化时触发通知(如温度变化超过1℃)
- 消息中间件集成:通过RabbitMQ等实现跨系统观察者模式
总结
观察者模式如同软件架构的"神经系统",通过事件驱动和状态广播机制,在GUI开发、物联网、金融交易等场景中展现出强大的生命力。其设计精髓在于将状态生产者与状态消费者解耦,开发者应重点把控通知粒度与性能平衡,结合具体场景选择同步/异步实现策略,从而构建出高响应、易扩展的现代化系统架构。