一、场景还原(先搞懂业务逻辑)
我们模拟一个极简的外卖系统:
- 用户在APP上下单(触发「下单事件」)
- 系统自动通知商家接单(事件处理器1)
- 系统自动给用户发下单成功短信(事件处理器2)
- 系统自动通知骑手准备取餐(事件处理器3)
核心本质 :某个事情发生了(触发事件),然后自动执行一堆预先设置好的逻辑(事件处理器)
二、代码实现(分步骤拆解)
1. 第一步:定义「事件」------ 告诉系统"发生了什么事"
事件就是一个普通的Java类,用来封装事件的关键信息(比如谁下的单、买了什么)。
java
// 外卖订单事件:封装订单的核心信息
class OrderPlacedEvent {
// 订单ID
private String orderId;
// 下单用户
private String userName;
// 外卖商品
private String foodName;
// 构造方法:创建事件时必须传入核心信息
public OrderPlacedEvent(String orderId, String userName, String foodName) {
this.orderId = orderId;
this.userName = userName;
this.foodName = foodName;
}
// Getter方法:让事件处理器能拿到事件信息
public String getOrderId() { return orderId; }
public String getUserName() { return userName; }
public String getFoodName() { return foodName; }
}
核心作用:把事件的关键数据打包成一个对象,方便后续处理器使用。
2. 第二步:定义「事件处理器接口」------ 约定"事件发生后要做什么"
这是事件驱动的核心契约,规定了所有处理器必须遵守的规则(就像外卖平台规定商家必须在5分钟内接单)。
java
// 订单事件处理器接口:所有处理订单事件的逻辑都要实现这个接口
@FunctionalInterface // 标记为函数式接口,方便用Lambda简化
interface OrderEventHandler {
// 只有一个方法:当订单事件发生时,执行这个方法
void handleOrderEvent(OrderPlacedEvent event);
}
核心作用:统一所有事件处理器的"行为标准",让系统能无缝对接任意处理器。
3. 第三步:实现「具体的事件处理器」------ 定义"具体要做的事"
我们针对场景中的三个动作,分别写三个处理器:
java
// 处理器1:通知商家接单
class MerchantNotifyHandler implements OrderEventHandler {
@Override
public void handleOrderEvent(OrderPlacedEvent event) {
System.out.println("[商家通知] 订单" + event.getOrderId() + "已收到,用户" + event.getUserName() + "点了" + event.getFoodName() + ",请尽快准备!");
}
}
// 处理器2:给用户发下单成功短信
class UserSmsHandler implements OrderEventHandler {
@Override
public void handleOrderEvent(OrderPlacedEvent event) {
System.out.println("[用户短信] 亲爱的" + event.getUserName() + ",您的订单" + event.getOrderId() + "已提交,我们会尽快为您配送!");
}
}
// 处理器3:通知骑手准备取餐
class RiderNotifyHandler implements OrderEventHandler {
@Override
public void handleOrderEvent(OrderPlacedEvent event) {
System.out.println("[骑手通知] 订单" + event.getOrderId() + "已生成,请骑手前往商家" + event.getFoodName() + "取餐!");
}
}
核心作用:把具体业务逻辑和事件触发逻辑彻底解耦,比如以后要加"通知财务记账",只需要新增一个处理器就行,不用改下单的核心代码。
4. 第四步:定义「事件发布器」------ 负责"触发事件并通知所有处理器"
这是整个系统的调度中心,当用户下单时,它会创建事件,并通知所有注册好的处理器。
java
// 外卖订单服务:负责接收用户下单请求,触发事件
class OrderService {
// 用集合保存所有注册的事件处理器(支持多个处理器)
private List<OrderEventHandler> handlers = new ArrayList<>();
// 注册处理器:把处理器加入集合(比如商家、用户、骑手的处理器都注册进来)
public void registerHandler(OrderEventHandler handler) {
handlers.add(handler);
}
// 用户下单:核心方法,触发事件
public void placeOrder(String orderId, String userName, String foodName) {
System.out.println("\n=== 用户" + userName + "下单成功 ===");
// 1. 创建事件对象(封装订单信息)
OrderPlacedEvent event = new OrderPlacedEvent(orderId, userName, foodName);
// 2. 通知所有注册的处理器(遍历集合,逐个调用handle方法)
for (OrderEventHandler handler : handlers) {
handler.handleOrderEvent(event);
}
}
}
核心作用:
- 负责事件的创建和分发,是事件和处理器之间的桥梁
- 支持动态添加处理器(比如旺季可以临时加一个"通知客服监控超时订单"的处理器)
5. 第五步:测试运行------模拟用户下单
java
import java.util.ArrayList;
import java.util.List;
public class SimpleEventDemo {
public static void main(String[] args) {
// 1. 创建订单服务(事件发布器)
OrderService orderService = new OrderService();
// 2. 注册所有事件处理器(把商家、用户、骑手的处理器都加进去)
orderService.registerHandler(new MerchantNotifyHandler());
orderService.registerHandler(new UserSmsHandler());
orderService.registerHandler(new RiderNotifyHandler());
// 3. 模拟用户下单(触发事件)
orderService.placeOrder("ORD20260601001", "张三", "麻辣香锅");
orderService.placeOrder("ORD20260601002", "李四", "黄焖鸡米饭");
}
}
运行结果:
=== 用户张三下单成功 ===
[商家通知] 订单ORD20260601001已收到,用户张三点了麻辣香锅,请尽快准备!
[用户短信] 亲爱的张三,您的订单ORD20260601001已提交,我们会尽快为您配送!
[骑手通知] 订单ORD20260601001已生成,请骑手前往商家麻辣香锅取餐!
=== 用户李四下单成功 ===
[商家通知] 订单ORD20260601002已收到,用户李四点了黄焖鸡米饭,请尽快准备!
[用户短信] 亲爱的李四,您的订单ORD20260601002已提交,我们会尽快为您配送!
[骑手通知] 订单ORD20260601002已生成,请骑手前往商家黄焖鸡米饭取餐!
三、核心思路整理(一张图记住整个流程)
用户下单 → OrderService.placeOrder() → 创建OrderPlacedEvent事件 → 遍历所有注册的OrderEventHandler → 逐个调用handleOrderEvent()方法
关键概念提炼(必背)
| 角色 | 作用 | 对应代码类 |
|---|---|---|
| 事件 | 封装"发生了什么事"的信息 | OrderPlacedEvent |
| 事件处理器接口 | 约定"事件发生后要执行什么"的规范 | OrderEventHandler |
| 具体处理器 | 实现具体的业务逻辑(比如发短信、通知) | MerchantNotifyHandler等 |
| 事件发布器 | 触发事件并通知所有处理器 | OrderService |
四、Java 8 简化优化(用Lambda减少冗余代码)
因为OrderEventHandler是函数式接口,我们可以直接用Lambda替代单独的处理器类,让代码更简洁:
java
public class LambdaEventDemo {
public static void main(String[] args) {
OrderService orderService = new OrderService();
// 用Lambda直接注册处理器,不用写单独的类
orderService.registerHandler(event ->
System.out.println("[商家通知] 订单" + event.getOrderId() + "已收到,用户" + event.getUserName() + "点了" + event.getFoodName() + ",请尽快准备!")
);
orderService.registerHandler(event ->
System.out.println("[用户短信] 亲爱的" + event.getUserName() + ",您的订单" + event.getOrderId() + "已提交,我们会尽快为您配送!")
);
orderService.placeOrder("ORD20260601003", "王五", "奶茶");
}
}
核心优势:对于简单的处理器逻辑,不用再写单独的实现类,直接用Lambda表达式传递,代码量减少一半。
订单事件类封装,
处理器分业务忙。
发布器传消息广,
Lambda简写韵悠长。