函数式接口 + 模板方法
函数式接口 + 模板方法的组合,将继承关系转变为组合关系:
固定流程由模板方法(execute 或 run)统一封装;
可变行为通过函数式接口参数传入,无需新建子类;
以xxljob任务实现为例。
- 函数式接口
java
@FunctionalInterface
public interface JobExecutor {
/**
* 执行任务核心逻辑
*/
ReturnT<String> execute(String param) throws Exception;
}
- 模板方法
java
// 固定流程,非核心逻辑
@Slf4j
@Component
public class JobExecuteTemplate {
/**
* 模板方法:固定执行流程,业务逻辑通过函数式接口参数注入
*/
public static ReturnT<String> execute(String jobName, JobExecutor executor) {
long startTime = System.currentTimeMillis();
String param = null;
try {
// 1. 统一获取参数
param = XxlJobHelper.getJobParam();
log.info("[{}] 任务开始执行,参数: {}", jobName, param);
// 2. 执行业务逻辑(由调用方通过 Lambda 传入)
ReturnT<String> result = executor.execute(param);
// 3. 处理成功结果
XxlJobHelper.handleSuccess(result.getMsg());
log.info("[{}] 任务执行成功,耗时: {}ms", jobName, System.currentTimeMillis() - startTime);
return result;
} catch (Exception e) {
// 4. 统一异常处理
log.error("[{}] 任务执行失败,参数: {}", jobName, param, e);
XxlJobHelper.handleFail("[{}] 执行失败: " + e.getMessage(), jobName);
return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
} finally {
// 5. 统一记录耗时
log.info("[{}] 任务执行结束,总耗时: {}ms", jobName, System.currentTimeMillis() - startTime);
}
}
}
- 业务使用
java
@XxlJob("cleanExpiredOrders")
public ReturnT<String> cleanExpiredOrders(String param) throws Exception {
// 仅需传入任务名称和核心业务逻辑(Lambda 表达式)
return JobExecuteTemplate.execute("清理过期订单", param -> {
// 解析参数(JSON 格式)
CleanOrderParam cleanParam = JSON.parseObject(param, CleanOrderParam.class);
int count = orderService.cleanExpiredOrders(cleanParam.getDays());
return ReturnT.SUCCESS;
});
}