观察者模式(Observer Pattern)
意图
定义对象间的一种 “一对多” 依赖关系,当一个对象(被观察者)的状态发生变化时,所有依赖它的对象(观察者)都会收到通知,并自动更新。
主要解决
• 需要在多个对象之间建立联动机制,保证数据同步或状态一致性。
• 降低耦合度,让对象之间的关系不需要直接引用,而是通过事件通知机制实现解耦。
何时使用
适用于以下场景:
1. 数据变化需要通知多个模块(如:GUI 事件、订阅-发布模式)
2. 对象之间存在依赖关系(如:MVC 设计模式)
3. 希望实现松耦合的消息传递机制(如:消息队列、事件驱动架构)
结构
观察者模式通常由以下组件组成:
1. Subject(被观察者):维护观察者列表,当自身状态发生变化时,通知所有观察者。
2. Observer(观察者):定义 update() 方法,当 Subject 发生变化时执行更新操作。
3. ConcreteSubject(具体被观察者):具体的业务对象,状态发生变化时调用 notifyObservers()。
4. ConcreteObserver(具体观察者):接收通知并执行相应操作。
类图
示例代码(Java 实现)
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(String message);
}
// 被观察者(Subject)
class Subject {
private List<Observer> observers = new ArrayList<>();
// 订阅观察者
public void attach(Observer observer) {
observers.add(observer);
}
// 取消订阅
public void detach(Observer observer) {
observers.remove(observer);
}
// 通知所有观察者
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
// 具体观察者A
class ConcreteObserverA implements Observer {
private String name;
public ConcreteObserverA(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到通知: " + message);
}
}
// 具体观察者B
class ConcreteObserverB implements Observer {
private String name;
public ConcreteObserverB(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到通知: " + message);
}
}
// 测试代码
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserverA("观察者1");
Observer observer2 = new ConcreteObserverB("观察者2");
subject.attach(observer1);
subject.attach(observer2);
System.out.println("被观察者状态改变,发送通知...");
subject.notifyObservers("状态已更新!");
}
}
输出结果
被观察者状态改变,发送通知...
观察者1 收到通知: 状态已更新!
观察者2 收到通知: 状态已更新!
优缺点
✅ 优点
1. 解耦合 —— 观察者和被观察者独立,不直接依赖彼此的具体实现。
2. 支持动态变化 —— 可以在运行时添加或移除观察者,提高灵活性。
3. 自动通知 —— 任何状态变化都会自动触发通知,避免手动检查状态的复杂性。
❌ 缺点
1. 通知机制可能引发性能问题 —— 如果观察者过多,或者更新逻辑复杂,可能导致广播通知的性能问题。
2. 难以控制通知顺序 —— 观察者的执行顺序通常不可控,在某些情况下可能导致不一致性。
3. 可能导致循环依赖 —— 需要谨慎设计,避免观察者又影响被观察者,形成死循环。
应用场景
|
场景 |
示例 |
|---|---|
|
GUI 事件驱动 |
按钮点击事件、窗口变化等 |
|
消息推送系统 |
订阅-发布模式,如微信公众号推送 |
|
模型-视图-控制器(MVC) |
视图监听模型数据的变化 |
|
股票市场 |
交易系统实时通知股价变化 |
|
游戏开发 |
玩家状态改变时通知多个 UI 组件 |
变体与扩展
• Java 内置 Observer 模式:Java 提供了 Observable 类和 Observer 接口,可以直接使用。
• 事件驱动架构(Event-Driven Architecture):类似 EventBus 机制,允许更灵活的事件分发。
• Reactive Programming(响应式编程):如 RxJava,观察者模式的升级版,支持异步流数据处理。
总结
1. 观察者模式用于一对多的依赖关系,让多个对象在目标对象状态变化时自动收到通知。
2. 核心思想是“订阅-通知”机制,使观察者和被观察者解耦,提高灵活性。
3. 适用于 GUI 事件、消息推送、数据联动等场景,但要注意性能和依赖管理。
浙公网安备 33010602011771号