Skip to content

观察者模式是事件驱动、消息通知的底层思想,也是最早接触的设计模式之一。之前写过一篇《设计模式:观察者模式和发布订阅模式的区别?》讲二者的差异,这篇把观察者模式本身系统地补全:它解决什么、怎么实现、和发布订阅到底差在哪。

一、解决什么问题

观察者模式解决的是**"一对多"的状态同步问题**:一个对象的状态变了,需要自动通知依赖它的多个对象。

典型场景:

  • 电商下单:下单成功后,要通知库存系统扣库存、通知积分系统加积分、通知短信系统发通知
  • 事件监听:按钮点击、消息到达,触发注册的监听器
  • 行情推送:股价变了,通知所有订阅的行情面板

核心思想一句话:主题维护一群观察者,状态一变就挨个通知,主题不需要知道"通知谁"以外的细节。

二、观察者模式怎么落地

两个角色:

  • 主题(Subject):维护观察者列表,提供 attach(注册)/detach(移除)/notify(通知)
  • 观察者(Observer):实现统一的 update 方法,接收通知
java
// ① 观察者接口
public interface Observer {
    void update(String message);
}

// ② 主题:维护观察者列表
public class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void attach(Observer o) { observers.add(o); }
    public void detach(Observer o) { observers.remove(o); }

    public void notifyObservers(String message) {
        for (Observer o : observers) {
            o.update(message);          // 挨个通知
        }
    }
}

// ③ 具体观察者
public class StockObserver implements Observer {
    public void update(String message) {
        System.out.println("库存系统收到: " + message);
    }
}

// 使用
Subject subject = new Subject();
subject.attach(new StockObserver());
subject.attach(new PointsObserver());
subject.notifyObservers("订单已支付");   // 两个观察者都被通知到

观察者模式结构:主题维护观察者列表,状态变化时挨个通知

三、观察者 vs 发布订阅(易混,重点)

这两个经常被混为一谈,核心区别在于"中间有没有一个消息分发器"

维度观察者模式发布订阅模式
耦合主题直接持有观察者列表双方互不知道,靠中间层
中间层有(EventBus / Message Broker)
执行方式通常同步直接调用通常异步,消息进队列
类比老师直接点名通知学生广播电台发信号,收音机自己收

用 12306 的例子(我之前旧文里详述过):候补购票里,12306 直接维护候补名单逐个通知,是观察者;如果中间加一层"消息分发器",12306 只发班次信息、由分发器去通知订票者,就是发布订阅

详细的图文对比可以看我旧文《设计模式:观察者模式和发布订阅模式的区别?》。

观察者 vs 发布订阅:观察者直接通知,发布订阅经中间消息分发器解耦

四、实际应用

观察者模式在现代框架里无处不在,只是换了名字:

  • Spring 的事件机制ApplicationEvent + @EventListener,发布事件 → 通知监听器
  • 消息队列:Kafka、RabbitMQ 的消费模型,本质是发布订阅的放大版(见《Kafka 快速入门》)
  • Java 原生Observable/Observer(已废弃,因为有局限性,建议自定义)

小结

  • 观察者模式解决"一对多"状态同步:主题维护观察者列表,状态一变挨个通知
  • 两角色:Subject(维护列表 + 通知)+ Observer(统一 update)
  • 与发布订阅的区别:中间有没有消息分发器(直接通知 vs 经中间层解耦)
  • 落地:Spring 事件、消息队列都是它的思想延伸

下一步可以看《责任链模式》——它也是"一个请求经过多个处理者",但和观察者"一对多广播"不同,责任链是"多个处理者依次尝试,谁处理谁停"(文章整理中)。想了解"算法可替换"的兄弟模式,看《策略模式》。