Java 观察者模式怎么写
在日常开发中,你肯定遇到过这样的场景:一款外卖APP,你下单后,不仅自己能收到订单确认通知,骑手会收到取餐提醒,商家也会收到接单通知。这三者不需要互相直接沟通,只要订单状态变化,就能自动同步各自需要的信息。这种“一个对象变了,其他相关对象自动收到通知”的逻辑,其实就是Java里观察者模式要解决的问题。
很多刚学Java的同学觉得设计模式太抽象,其实不用想复杂——观察者模式本质就是“订阅通知”:你订阅了某个消息,消息有变化就会通知你。接下来咱们就用生活化的例子,一步步说清楚怎么在Java里实现这个模式。

先搞懂两个核心角色
要写观察者模式,得先记住两个必不可少的角色,就像外卖系统里的“订单主体”和“通知接收者”:
- 主题(被观察者):就是那个会发生变化的对象,比如刚才说的“订单”,它要负责管理所有订阅它的观察者,还要在自己变化时通知大家。
- 观察者:就是需要接收通知的对象,比如外卖APP的用户、骑手、商家,只要订阅了主题,主题一变化,它们就得做出响应。
举个最贴近的例子:你关注的B站UP主(主题),粉丝(观察者)订阅了他,UP主发新视频时,粉丝会收到推送。这个逻辑完全对应观察者模式的两个角色,是不是一下子就不抽象了?
第一步:定义观察者接口(统一接收通知的规则)
观察者们都得遵守同一个“收通知的规矩”,不然不同的粉丝、商家收消息的格式不一样,主题通知起来就乱了。所以我们先写一个简单的观察者接口,只定义一个“收到通知就干活”的方法。
比如用Java代码写的话,接口大概是这样:
`java
// 观察者接口:所有需要接收通知的对象都实现它
public interface Observer {
// 收到通知时调用的方法,参数是通知内容
void update(String message);
}
`
就像所有粉丝都得知道“UP主发新视频了,我要收到推送”,这个接口就是统一的“收通知规则”,不管是粉丝还是商家,只要实现这个接口,就能当观察者。
第二步:定义主题接口(管理观察者的规则)
主题(被观察者)得会做三件事:加观察者、删观察者、通知所有观察者,所以我们也给它写一个统一的接口,不管是订单还是UP主,都遵守这个规则:
`java
// 主题接口:所有被观察的对象都实现它
public interface Subject {
// 注册观察者(相当于订阅)
void registerObserver(Observer observer);
// 移除观察者(相当于取消订阅)
void removeObserver(Observer observer);
// 通知所有已注册的观察者
void notifyObservers();
}
`
这个接口就像B站的“关注管理系统”,你可以订阅、取关,UP主发新内容时,系统会通知所有订阅的粉丝。
第三步:实现具体的主题和观察者
光有接口没用,得写具体的类来实现它们,咱们用UP主和粉丝的例子来落地:
- 具体主题(UP主类):它要实现Subject接口,还要存自己的状态(比如有没有发新视频),状态变了就通知观察者。
- 具体观察者(粉丝类):实现Observer接口,收到通知后就做出对应的反应(比如打开B站看新视频)。
写出来的代码大概是这样:
`java
// 具体主题:UP主,实现Subject接口
public class UpMain implements Subject {
// 存所有订阅的粉丝
private List<Observer> observers = new ArrayList<>();
// UP主的状态:有没有发新视频
private String latestVideo;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
// 遍历所有观察者,挨个发通知
for (Observer observer : observers) {
observer.update("UP主发新视频啦:" + latestVideo);
}
}
// 专门的方法:UP主发新视频时,更新状态并通知
public void uploadVideo(String videoName) {
this.latestVideo = videoName;
System.out.println("UP主上传了新视频:" + videoName);
// 状态变了,通知所有粉丝
notifyObservers();
}
}
// 具体观察者:粉丝,实现Observer接口
public class Fan implements Observer {
private String name;
public Fan(String name) {
this.name = name;
}
@Override
public void update(String message) {
// 收到通知后的反应
System.out.println(name + " 收到通知:" + message);
}
}
`
这样就把核心逻辑写完了,是不是很清晰?
第四步:测试一下整个流程
最后我们写个测试类,模拟真实使用场景,看看观察者模式是不是真的能用:
`java
public class TestObserver {
public static void main(String[] args) {
// 1. 创建主题(UP主)
UpMain upMain = new UpMain();
// 2. 创建观察者(两个粉丝)
Observer fan1 = new Fan("小明");
Observer fan2 = new Fan("小红");
// 3. 粉丝订阅UP主
upMain.registerObserver(fan1);
upMain.registerObserver(fan2);
// 4. UP主发新视频,自动通知所有粉丝
upMain.uploadVideo("Java观察者模式入门");
}
}
`
运行测试类,你会看到输出:
UP主上传了新视频:Java观察者模式入门
小明 收到通知:UP主发新视频啦:Java观察者模式入门
小红 收到通知:UP主发新视频啦:Java观察者模式入门
完美实现了“主题变化,观察者自动收到通知”的效果。
最后再提一句,Java其实已经自带了观察者模式的实现类(Observable类和Observer接口),但自己手写更灵活,也能帮你彻底搞懂原理——毕竟不管框架怎么封装,核心还是“一个变了,通知所有相关对象”这个逻辑。