观察者模式
观察者模式用于定义对象之间一对多的通知关系。当主题对象发生变化时,所有观察者都会收到通知。
一句话理解:一个对象变了,自动通知关心它的人。
解决什么问题
订单支付成功后,可能要做很多事情:
text
更新订单状态
发送短信
发放积分
推送站内信
通知仓库发货如果这些逻辑都写在支付方法里,支付服务会越来越臃肿。观察者模式把后续动作拆成多个观察者,由事件通知触发。
基本结构
text
Subject
-> addObserver()
-> removeObserver()
-> notifyObservers()
Observer
-> update()角色:
Subject:被观察者,维护观察者列表。Observer:观察者,接收通知。ConcreteObserver:具体观察者。
Java 示例
事件对象:
java
class OrderPaidEvent {
private final long orderId;
private final int amount;
OrderPaidEvent(long orderId, int amount) {
this.orderId = orderId;
this.amount = amount;
}
public long orderId() {
return orderId;
}
public int amount() {
return amount;
}
}观察者接口:
java
interface OrderPaidObserver {
void onPaid(OrderPaidEvent event);
}具体观察者:
java
class SmsObserver implements OrderPaidObserver {
public void onPaid(OrderPaidEvent event) {
System.out.println("send sms for order " + event.orderId());
}
}
class PointsObserver implements OrderPaidObserver {
public void onPaid(OrderPaidEvent event) {
System.out.println("add points for order " + event.orderId());
}
}主题:
java
import java.util.ArrayList;
import java.util.List;
class OrderEventPublisher {
private final List<OrderPaidObserver> observers = new ArrayList<>();
public void addObserver(OrderPaidObserver observer) {
observers.add(observer);
}
public void publish(OrderPaidEvent event) {
for (OrderPaidObserver observer : observers) {
observer.onPaid(event);
}
}
}使用:
java
OrderEventPublisher publisher = new OrderEventPublisher();
publisher.addObserver(new SmsObserver());
publisher.addObserver(new PointsObserver());
publisher.publish(new OrderPaidEvent(1001L, 9900));使用场景
- 事件通知。
- 消息发布订阅。
- Spring 事件机制。
- 前端事件监听。
- 订单支付后异步扩展动作。
优点
- 主题和观察者解耦。
- 新增观察者不需要修改主题。
- 支持一对多通知。
- 适合扩展后续动作。
缺点
- 同步通知时,一个观察者异常可能影响后续观察者。
- 观察者太多会影响性能。
- 通知顺序如果有业务含义,需要明确设计。
- 异步事件会带来最终一致性问题。
和发布订阅的区别
观察者模式通常是主题直接持有观察者。
发布订阅通常有一个消息中心,发布者和订阅者互相不知道对方。
text
观察者:Subject -> Observer
发布订阅:Publisher -> EventBus -> Subscriber实战注意
支付、订单这类核心链路不要随便把强一致动作拆成异步观察者。能异步的是通知、积分、日志等旁路动作;核心状态变更要保证可靠性。