Java内置观察者怎么用
在 Java 中,内置观察者模式主要体现在早期版本提供的java.util.Observable(被观察者)和 java.util.Observer(观察者)接口上。
⚠️ 注意:
从 Java 9 开始,这两个类已被标记为@Deprecated,官方不再推荐使用,推荐改用PropertyChangeListener、Flow API或第三方方案(如 Guava、RxJava)。
但很多老代码、面试或学习设计模式时仍然会用到,所以理解它仍然有价值。
一、核心类说明
1️⃣ Observable(被观察者)
- 表示“被观察的对象”
- 主要方法:
void addObserver(Observer o) // 添加观察者
void deleteObserver(Observer o) // 删除观察者
void notifyObservers() // 通知所有观察者
void notifyObservers(Object arg)// 带参数的通知
void setChanged() // 标记状态已改变
2️⃣ Observer(观察者)
- 只有一个方法:
void update(Observable o, Object arg)
二、使用示例(经典写法)
1️⃣ 定义被观察者(继承 Observable)
import java.util.Observable;
public class NewsPublisher extends Observable {
private String news;
public void publishNews(String news) {
this.news = news;
setChanged(); // 必须调用,否则不会通知
notifyObservers(news); // 通知观察者
}
public String getNews() {
return news;
}
}
2️⃣ 定义观察者(实现 Observer)
import java.util.Observable;
import java.util.Observer;
public class Reader implements Observer {
private String name;
public Reader(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof NewsPublisher) {
System.out.println(name + " 收到新闻: " + arg);
}
}
}
3️⃣ 测试代码
public class ObserverTest {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
Reader r1 = new Reader("张三");
Reader r2 = new Reader("李四");
publisher.addObserver(r1);
publisher.addObserver(r2);
publisher.publishNews("Java 9 发布了!");
}
}
✅ 输出结果
张三 收到新闻: Java 9 发布了!
李四 收到新闻: Java 9 发布了!
三、执行流程总结
- 被观察者继承
Observable - 观察者实现
Observer - 被观察者:
- 调用
setChanged() - 调用
notifyObservers()
- 调用
- 观察者:
update()被自动回调
四、存在的问题(为什么被废弃)
| 问题 | 说明 |
|---|---|
| 非线程安全 | Observable 内部未处理好并发 |
| 继承限制 | 必须继承 Observable,不支持组合 |
| API 设计老旧 | 不符合现代 Java 风格 |
| 不灵活 | 无法区分事件类型 |
五、现代替代方案(推荐)
✅ 1. PropertyChangeListener(JavaBeans 风格)
PropertyChangeSupport support = new PropertyChangeSupport(this);
support.addPropertyChangeListener(evt -> { ... });
support.firePropertyChange("news", oldVal, newVal);
✅ 2. Java 9+ Flow API(响应式)
Flow.Publisher
Flow.Subscriber
✅ 3. 第三方
- Guava EventBus
- RxJava / Reactor
- Spring ApplicationEvent
六、一句话总结
Java 内置观察者 = 继承
Observable+ 实现Observer+setChanged()+notifyObservers()
但已过时,实际项目中不推荐使用。
如果你愿意,我可以:
- ✅ 用 Spring Event 重写这个例子
- ✅ 对比 观察者 vs 发布订阅
- ✅ 画一张 观察者模式 UML 图