My App

观察者模式

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 addEventListenerRedis 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)

On this page