核心在于用枚举作键、EnumMap查表、Consumer封装逻辑,实现类型安全、O(1)分发、可测试可热插拔的指令调度。

直接用 switch 配合 Consumer 实现指令分发,核心在于把每个 case 的处理逻辑封装成 Consumer 实例,再通过统一入口按类型查表执行,避免重复判断、硬编码分支,也规避字符串 switch 的哈希开销和线性匹配风险。
用枚举定义指令类型,替代字符串或数字
枚举天然具备类型安全、可枚举、可映射的特点,是 Consumer 分发的理想键类型。不要用 "pickup" 或 1 作 case 条件,改用:
public enum TaskCommand {
PICKUP,
DELIVERY,
TRANSFER
}这样编译期可校验,IDE 可补全,运行时无哈希计算,switch 枚举会生成高效 tableswitch 字节码。
用 EnumMap 存储 Consumer 映射关系
声明一个静态 final 的 EnumMap<taskcommand consumer>></taskcommand>,在类初始化时完成注册:
private static final EnumMap<taskcommand consumer>> HANDLERS = new EnumMap(TaskCommand.class);
static {
HANDLERS.put(TaskCommand.PICKUP, ctx -> {
handlePickup(ctx);
updateStatus(ctx, "ING");
});
HANDLERS.put(TaskCommand.DELIVERY, ctx -> {
handleDelivery(ctx);
updateStatus(ctx, "ING");
});
HANDLERS.put(TaskCommand.TRANSFER, ctx -> {
handleTransfer(ctx);
updateStatus(ctx, "ING");
});
}</taskcommand>相比 HashMap,EnumMap 内部用数组实现,索引即枚举的 ordinal 值,真正 O(1) 查找,且内存更紧凑。
分发方法只需两行:查表 + 执行
主调度逻辑变得极简,不再有 switch 块,也不需要 default 处理空指针或未知类型:
public void dispatch(TaskCommand cmd, TaskContext context) {
Consumer<taskcontext> handler = HANDLERS.get(cmd);
if (handler == null) {
throw new IllegalArgumentException("不支持的指令: " + cmd);
}
handler.accept(context);
}</taskcontext>这种写法天然支持热插拔(运行时替换 Consumer 实例),也便于单元测试——你可以传入 mock Consumer 验证行为,无需启动整个流程。
进阶:支持带返回值或异常透传
若某些指令需返回结果(如任务 ID)或明确抛出业务异常,可升级为 BiFunction 或自定义函数接口:
- 用
EnumMap<taskcommand function string>></taskcommand>处理需返回值的场景 - Consumer 本身不声明受检异常,但可在内部用 RuntimeException 包装并抛出,由上层统一捕获
- 如需区分不同异常语义,可定义
TaskHandler<t></t>接口,含T handle(TaskContext)方法
指令分发的本质不是语法选择,而是解耦“识别”与“执行”。switch + Consumer 的组合,让识别收敛到枚举查表,执行下沉为可测试、可替换、可复用的函数对象——这比层层 if-else 或裸 switch 更贴近高内聚、低耦合的设计本意。











