函数式接口解耦核心是分离“做什么”与“怎么做”,主流程仅依赖单一抽象方法接口(如OrderStateHandler、Consumer<T>),通过运行时注入Lambda或方法引用实现逻辑替换,配合非空防护提升健壮性。

在业务代码中用函数式接口解耦,关键不是多写接口,而是让“做什么”和“怎么做”真正分开——主流程只管调用契约,具体行为由外部注入,改逻辑不碰主干。
定义清晰、单一的函数式接口
接口必须只有一个抽象方法,加上@FunctionalInterface注解强制校验。别为了复用硬塞多个方法,职责越聚焦,后续越容易替换和测试。
- 比如订单状态变更处理,就定义
OrderStateHandler,只留void handle(Order order) - 避免把日志、风控、通知全揉进一个接口;该拆就拆,比如
NotificationHandler、RiskChecker各自独立 - 优先复用
java.util.function里的标准类型:无返回用Consumer<T>,有返回用Function<T, R>,判断用Predicate<T>
主流程只依赖接口参数,不 new 实现类
业务方法签名直接接收函数式接口,内部不做任何分支判断或实现类实例化。这样同一段代码,传不同 Lambda 就能跑通测试、灰度、生产等场景。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 例如
OrderService.process(Order order, Consumer<Order> afterProcess) - 方法体内只写
afterProcess.accept(order),完全不关心背后是发短信、写 DB 还是打日志 - 如果某处需要多个动作,可组合:比如
Consumer<Order> handler = log::info.andThen(sms::send).andThen(metrics::record)
运行时动态传入行为,替换成本极低
不用提前注册 Spring Bean,也不用维护策略 Map,调用点一行 Lambda 或方法引用就搞定。新增逻辑不改老代码,回归范围自然缩小。
立即学习“Java免费学习笔记(深入)”;
- 测试时:
process(order, o -> System.out.println("mock: " + o.getId())) - 生产发券:
process(order, couponService::issue) - 风控拦截:
process(order, o -> { if (!riskPass(o)) throw new RiskRejectException(); }) - 临时降级:
process(order, o -> {})—— 空实现,零改动切掉整条链路
配合判空与默认行为提升健壮性
函数式接口参数可能为 null,尤其来自配置或外部调用时。加一层防护,比线上报 NPE 强得多。
- 调用前加
if (handler != null) handler.accept(order) - 或提供默认行为:
Objects.requireNonNullElse(handler, o -> {}) - 对关键路径,可封装成工具方法:
safeAccept(handler, order),内部统一做非空+异常捕获

















