Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

观察者模式

观察者模式用于定义对象之间一对多的通知关系。当主题对象发生变化时,所有观察者都会收到通知。

一句话理解:一个对象变了,自动通知关心它的人。

解决什么问题

订单支付成功后,可能要做很多事情:

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

实战注意

支付、订单这类核心链路不要随便把强一致动作拆成异步观察者。能异步的是通知、积分、日志等旁路动作;核心状态变更要保证可靠性。

以工程实践沉淀知识,以文档复盘成长。