0Pricing
Java Academy · 课时

观察者模式:事件通知

在股票价格系统中实现 Observer,将事件生产者与消费者解耦

观察者模式:事件通知 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

Observer 的意图

Observer(也称为发布-订阅)定义了一对多的依赖关系:当主题的状态发生变化时,所有已注册的观察者都会自动收到通知。

主题与 Observer 接口

主题会维护观察者列表并通知它们。观察者实现 update 方法,以响应事件。

public interface Observer {
    void update(String event, Object data);
}
public interface Subject {
    void addObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers(String event, Object data);
}

具体主题:Stock Ticker

主题持有状态,并在状态发生变化时调用 notifyObservers。它负责管理观察者列表。

public class StockTicker implements Subject {
    private final List<Observer> observers = new ArrayList<>();
    private double price;
    public void addObserver(Observer o)    { observers.add(o); }
    public void removeObserver(Observer o) { observers.remove(o); }
    public void setPrice(double p) {
        this.price = p;
        notifyObservers("PRICE_CHANGED", p);
    }
    public void notifyObservers(String ev, Object data) {
        for (Observer o : observers) o.update(ev, data);
    }
}

具体观察者

每个观察者都可以对同一通知做出不同反应。您可以在运行时添加观察者,而无需修改主题。

public class AlertSystem implements Observer {
    public void update(String ev, Object data) {
        if ((double) data < 100) System.out.println("ALERT: Low price!");
    }
}
public class Logger implements Observer {
    public void update(String ev, Object data) {
        System.out.println("LOG: " + ev + " = " + data);
    }
}

连接观察者

请在主题上注册观察者。主题发生变化时,它们都会做出响应。取消注册即可停止接收更新。

StockTicker ticker = new StockTicker();
ticker.addObserver(new AlertSystem());
ticker.addObserver(new Logger());
ticker.setPrice(95.5); // both observers notified

java.util.Observable——已弃用

JDK 曾提供 java.util.Observable 和 java.util.Observer,但它们自 Java 9 起已被弃用。请自行实现,或使用 RxJava、Project Reactor 等响应式库。

PropertyChangeListener

Java bean 提供了 PropertyChangeSupport,这是一种内置的观察者机制,用于监听 bean 属性变化,在 Swing 和 JavaFX 中得到广泛使用。

public class Model {
    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private int value;
    public void addPropertyChangeListener(PropertyChangeListener l) { pcs.addPropertyChangeListener(l); }
    public void setValue(int v) {
        int old = this.value; this.value = v;
        pcs.firePropertyChange("value", old, v);
    }
}

使用 Consumer 的函数式观察者

可以使用 Consumer<T> 作为轻量级观察者,而不是专门定义一个接口,非常适合简单的事件回调。

List<Consumer<Double>> listeners = new ArrayList<>();
listeners.add(p -> { if (p < 100) System.out.println("Low price"); });
listeners.add(p -> System.out.println("Price: " + p));
double newPrice = 95.5;
listeners.forEach(l -> l.accept(newPrice));

Observer 与事件总线

事件总线(例如 Guava EventBus)可以进一步解耦主题和观察者:主题将事件发布到总线,而无需知道谁在监听。观察者通过方法注解进行订阅。

// Guava EventBus example
EventBus bus = new EventBus();
bus.register(new Logger());       // subscribe
bus.post(new PriceEvent(95.5));   // publish

Observer 中的线程安全

如果观察者可能由多个线程添加或移除,请使用 synchronized 保护列表,或者在通知频繁的工作负载中使用 CopyOnWriteArrayList。

private final List<Observer> observers = new CopyOnWriteArrayList<>();

避免内存泄漏

观察者列表中的强引用会阻止垃圾回收。请使用 WeakReference<Observer>,或者在观察者不再需要时始终取消注册。

真实框架中的 Observer

Spring 的 ApplicationEventPublisher、Android LiveData 和 JavaFX 属性,都是不同抽象层次上的 Observer 模式实现。

快速检查

Observer 模式的主要优势是什么?

回顾

Observer 定义了一条一对多的通知链。您可以通过接口或函数式 Consumer 实现它。请使用 CopyOnWriteArrayList 保证线程安全,并始终取消观察者注册以防止内存泄漏。

常见问题解答

「观察者模式:事件通知」课时是免费的吗?

是的 — 「观察者模式:事件通知」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「观察者模式:事件通知」这节课中我会学到什么?

在股票价格系统中实现 Observer,将事件生产者与消费者解耦 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「观察者模式:事件通知」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 观察者模式:事件通知
  2. 策略模式:可互换算法
  3. 命令模式:封装操作
  4. 模板方法:定义算法骨架
← 返回 Java Academy