Java 观察者模式怎么写

在日常开发中,你肯定遇到过这样的场景:一款外卖APP,你下单后,不仅自己能收到订单确认通知,骑手会收到取餐提醒,商家也会收到接单通知。这三者不需要互相直接沟通,只要订单状态变化,就能自动同步各自需要的信息。这种“一个对象变了,其他相关对象自动收到通知”的逻辑,其实就是Java里观察者模式要解决的问题。

很多刚学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接口),但自己手写更灵活,也能帮你彻底搞懂原理——毕竟不管框架怎么封装,核心还是“一个变了,通知所有相关对象”这个逻辑。

上一篇 Swift编程语言入门:从核心概念到实际开发应用的知识科普