观察者模式:事件通知
在股票价格系统中实现 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 notifiedjava.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)); // publishObserver 中的线程安全
如果观察者可能由多个线程添加或移除,请使用 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 反馈 — 无需本地设置。
此课程中的所有课时
- 观察者模式:事件通知
- 策略模式:可互换算法
- 命令模式:封装操作
- 模板方法:定义算法骨架