接口定义回调契约确保解耦,抽象类封装共性流程实现复用:接口声明onSuccess/onFailure等方法并支持泛型,抽象类提供executeAsync模板及线程管理,二者组合通过依赖注入实现松耦合与高内聚。

Java 中接口与抽象类结合回调机制实现业务解耦,关键不在“谁替代谁”,而在于“各司其职”:接口定义回调契约,抽象类封装共性流程,二者配合让业务逻辑既松耦合又易复用。
接口负责定义回调契约,确保解耦边界清晰
回调的核心是“约定行为,不依赖实现”。必须用接口——它天然支持多实现、无状态、无构造逻辑,完美承载通知语义:
- 只声明一个或少数几个方法,如
onSuccess(Result result)、onFailure(String reason),避免混入生命周期或辅助方法; - 推荐使用泛型增强类型安全,例如
Callback,防止运行时转型错误; - 方法参数坚持“最小必要原则”,只传业务真正需要的数据,比如订单ID和支付金额,不传上下文对象或工具类实例;
- 所有方法默认为 public abstract,不提供默认实现(除非是纯日志、埋点等通用横切逻辑,且明确标注为非核心语义)。
抽象类封装公共执行流程,收敛重复逻辑
当多个业务模块(如支付回调、退款回调、发货回调)共享相似的异步执行结构时,抽象类可提取共性,但不触碰回调细节:
- 定义模板方法(如
executeAsync()),内部调用doBusinessLogic()(由子类实现)和notifyCallback()(统一判空+分发); - 内置线程管理(如复用
ExecutorService)、重试策略、超时控制等,子类无需重复编码; - 把回调对象作为 protected 字段持有,由子类在构造或初始化时注入,不强制要求 Spring 管理;
- 不实现回调接口本身,也不在抽象类里写
onSuccess的具体逻辑——那属于实现类的职责。
组合使用:抽象类持接口引用,子类专注业务响应
典型结构是“抽象类 + 接口 + 具体实现类”三层协作:
- 抽象类(如
AsyncOrderProcessor)接收并保存OrderCallback实例,在后台任务完成后统一触发callback.onPaid(...); - 接口(如
OrderCallback)仅含onPaid、onFailed等方法,由不同业务方各自实现; - 具体子类(如
InventoryUpdateProcessor、SmsNotifyProcessor)继承抽象类,实现自己的业务逻辑,并在回调方法中只做一件事:更新库存 或 发短信。
注意规避常见陷阱
这种组合虽强大,但容易误用:
- 不要让抽象类实现回调接口——这会把通知逻辑和执行流程强绑,违背解耦初衷;
- 不要在抽象类里 new 具体回调实现类——那等于硬编码依赖,应回调对象由外部注入;
- 若使用 Lambda 表达式注册回调(如
processor.setCallback(r -> log.info("OK"))),需确保其不捕获长生命周期对象,防止内存泄漏; - 多个监听器场景下,抽象类中的通知分发需加 try-catch 包裹每个回调调用,避免一个失败中断全部。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











