观察者模式
Observer — 定义一对多的依赖关系,状态变化时自动通知所有观察者
一句话理解
一个对象(Subject)状态变了,所有关注它的对象(Observer)自动收到通知。就像关注了一个 UP 主,他发视频你就会收到推送。
解决什么问题
- 一个对象变化后,需要通知多个其他对象
- 不想让通知方和被通知方紧耦合(通知方不需要知道具体有谁在监听)
怎么写
// 观察者接口
public interface Observer {
void update(String message);
}
// 被观察者(Subject)
public class Channel {
private final String name;
private final List<Observer> observers = new ArrayList<>();
public Channel(String name) { this.name = name; }
public void subscribe(Observer o) { observers.add(o); }
public void unsubscribe(Observer o) { observers.remove(o); }
// 发布内容 → 通知所有观察者
public void publish(String video) {
System.out.println(name + " 发布了: " + video);
for (Observer o : observers) {
o.update(name + " 发布了新视频: " + video);
}
}
}
// 具体观察者
public class User implements Observer {
private final String name;
public User(String name) { this.name = name; }
@Override
public void update(String message) {
System.out.println(name + " 收到通知: " + message);
}
}Channel ch = new Channel("技术频道");
User u1 = new User("张三");
User u2 = new User("李四");
ch.subscribe(u1);
ch.subscribe(u2);
ch.publish("设计模式入门");
// 技术频道 发布了: 设计模式入门
// 张三 收到通知: 技术频道 发布了新视频: 设计模式入门
// 李四 收到通知: 技术频道 发布了新视频: 设计模式入门和发布-订阅模式的区别
| 观察者模式 | 发布-订阅模式 | |
|---|---|---|
| 耦合 | 观察者直接注册到 Subject | 发布者和订阅者互不知道对方 |
| 中间层 | 无 | 有事件中心/消息代理 |
| 典型 | DOM addEventListener | Redis Pub/Sub、EventEmitter |
发布-订阅是观察者模式的进一步解耦版本。
前端中的观察者
// DOM 事件就是观察者模式
button.addEventListener('click', handleClick)
// Zustand 的 vanilla store 也是观察者模式
const listeners = new Set()
const subscribe = (listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
}
// setState 时通知所有 listener
listeners.forEach((listener) => listener(state))使用场景
- DOM 事件系统(addEventListener)
- Vue/React 的响应式系统
- Zustand、Redux 的 subscribe 机制
- Java 的
java.util.Observer(已废弃,但思想不变) - Spring 的
ApplicationEvent事件机制 - 消息队列(Kafka、RabbitMQ)