模板模式
模板方法模式是一种行为型设计模式,用于定义一个算法的骨架,而将一些步骤的实现延迟到子类中。
案例
案例一 service服务模板
接口ServiceTemplate 定义了模板方法,而具体的实现类则实现了这个方法,方法里面定义流程(算法骨架),同时调用了传入的 TemplateAction 接口的方法来完成特定的业务逻辑。
接口TemplateAction 定义了四个方法,是上面服务流程中的一些固定方法,然后定义一个抽象类实现这个方法,给出几个默认实现。避免其他接口直接实现TemplateAction的时候需要实现所有的方法。
- 模板方法定义: 在 ServiceTemplate 接口中定义了模板方法。
- 具体实现: ServiceTemplate 接口的实现类实现了模板方法,规定了一个算法的骨架,其中包含了一些固定的步骤。
- 流程委托: 具体实现类中的模板方法中,调用了传入的 TemplateAction 接口的方法,完成了具体的业务逻辑。这里的 TemplateAction 接口扮演了一个角色,提供了一组可定制的算法步骤。
- 默认实现: 通过在抽象类中给出 TemplateAction 接口方法的默认实现,避免了其他接口直接实现 TemplateAction 接口时需要实现所有方法的问题,提高了代码的灵活性和可维护性。
总的来说,这个案例符合模板方法模式的基本思想,通过定义模板方法和委托流程来实现算法的复用和扩展。
public interface ServiceTemplate {
/**
* run in datasource and execute Transaction
* @param action
* @param <T>
* @return
*/
<T> CallResult<T> execute(TemplateAction<T> action);
/**
* run in datasource and not execute Transaction
* @param action
* @param <T>
* @return
*/
<T> CallResult<T> executeQuery(TemplateAction<T> action);
}
@Component
@Slf4j
public class ServiceTemplateImpl implements ServiceTemplate {
@Override
public <T> CallResult<T> execute(TemplateAction<T> action) {
try{
CallResult<T> callResult = action.checkParam();
if(callResult==null){
log.warn("execute: Null result while checkParam");
return CallResult.fail(BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getMsg());
}
if(!callResult.isSuccess()){
return callResult;
}
callResult = action.checkBiz();
if(callResult==null){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.warn("execute: Null result while checkBiz");
return CallResult.fail(BusinessCodeEnum.CHECK_BIZ_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_BIZ_NO_RESULT.getMsg());
}
if(!callResult.isSuccess()){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return callResult;
}
long start = System.currentTimeMillis();
CallResult<T> cr= action.doAction();
log.info("execute datasource method run time:{}ms", System.currentTimeMillis() - start);
if (cr == null){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return CallResult.fail(BusinessCodeEnum.CHECK_ACTION_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_ACTION_NO_RESULT.getMsg());
}
if (!cr.isSuccess()){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return cr;
}
if(cr.isSuccess()){
action.finishUp(cr);
}
return cr;
}catch(Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
log.error("excute error", e);
return CallResult.fail();
}
}
@Override
public <T> CallResult<T> executeQuery(TemplateAction<T> action) {
try{
CallResult<T> callResult = action.checkParam();
if(callResult==null){
log.warn("executeQuery: Null result while checkParam");
return CallResult.fail(BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getMsg());
}
if(!callResult.isSuccess()){
return callResult;
}
callResult = action.checkBiz();
if(callResult==null){
log.warn("executeQuery: Null result while checkBiz");
return CallResult.fail(BusinessCodeEnum.CHECK_BIZ_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_BIZ_NO_RESULT.getMsg());
}
if(!callResult.isSuccess()){
return callResult;
}
long start = System.currentTimeMillis();
CallResult<T> cr= action.doAction();
log.info("executeQuery datasource method run time:{}ms", System.currentTimeMillis() - start);
if (cr == null){
return CallResult.fail(BusinessCodeEnum.CHECK_ACTION_NO_RESULT.getCode(), BusinessCodeEnum.CHECK_ACTION_NO_RESULT.getMsg());
}
if (!cr.isSuccess()){
return cr;
}
if(cr.isSuccess()){
action.finishUp(cr);
}
return cr;
}catch(Exception e){
e.printStackTrace();
log.error("executeQuery error", e);
return CallResult.fail();
}
}
}
public interface TemplateAction<T> {
//第一步 检查参数
CallResult<T> checkParam();
//第二步 检查业务逻辑是否符合需求
CallResult<T> checkBiz();
//第三步 执行
CallResult<T> doAction();
//第四步 执行完成之后 要进行的操作
void finishUp(CallResult<T> callResult);
}
public abstract class AbstractTemplateAction<T> implements TemplateAction<T> {
@Override
public CallResult<T> checkParam() {
return CallResult.success();
}
@Override
public CallResult<T> checkBiz() {
return CallResult.success();
}
@Override
public void finishUp(CallResult<T> callResult) {
}
}