设计模式-模板
Posted 熊猫小牛牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-模板相关的知识,希望对你有一定的参考价值。
场景
模板模式适合:父类控制业务处理流程,子类负责业务逻辑具体处理逻辑,换一种说法就是父类控制算法主流程,子类实现个性化步骤。典型案例就是spring的JdbcTemplate。
demo
假设有个场景:计算不同环境下产品的保质期时间。整个业务流程:
1. 预处理产品输入时间;
2. 计算常温状态产品保质期;
3. 个性化处理特殊场景下保质期。
定义抽象类,控制业务处理流程:
public abstract class AbstractEffectExpireCalc
public CalcResult calc(CalcRequest input)
CalcRequest inputCanbeUse = input;
// 预处理产品的生产日期
prepareCalc(inputCanbeUse);
// 常规计算
CalcResult result = regularClac(inputCanbeUse);
// 不同存储条件下计算产品保质期
specicalCalc(inputCanbeUse, result);
return result;
abstract void prepareCalc(CalcRequest inputCanbeUse);
abstract void specicalCalc(CalcRequest inputCanbeUse, CalcResult result);
private CalcResult regularClac(CalcRequest inputCanbeUse)
CalcResult result = new CalcResult();
result.setEffectTime(inputCanbeUse.getCreateTime());
return result;
2个子类实现:
public class RegularEnvCalc extends AbstractEffectExpireCalc
@Override
void prepareCalc(CalcRequest inputCanbeUse)
System.out.println("常温环境-不做预处理");
@Override
void specicalCalc(CalcRequest inputCanbeUse, CalcResult result)
result.setExpireTime(inputCanbeUse.getCreateTime() + 10000);
public class ColdEnvCalc extends AbstractEffectExpireCalc
@Override
void prepareCalc(CalcRequest inputCanbeUse)
System.out.println("寒冷环境-不做预处理");
@Override
void specicalCalc(CalcRequest inputCanbeUse, CalcResult result)
result.setExpireTime(inputCanbeUse.getCreateTime()+ 20000);
CalcRequest:
public class CalcRequest implements Serializable
private static final long serialVersionUID = 4444396583894965214L;
/**
* 生产日期
*/
private long createTime;
public CalcRequest()
public long getCreateTime()
return createTime;
public void setCreateTime(long createTime)
this.createTime = createTime;
@Override
public String toString()
return "CalcRequest" +
"createTime=" + createTime +
'';
CalcResult:
public class CalcResult implements Serializable
private static final long serialVersionUID = -8600570365855077191L;
/**
* 保质期-生效时间
*/
private long effectTime;
/**
* 保质期过期时间
*/
private long expireTime;
public CalcResult()
public long getEffectTime()
return effectTime;
public void setEffectTime(long effectTime)
this.effectTime = effectTime;
public long getExpireTime()
return expireTime;
public void setExpireTime(long expireTime)
this.expireTime = expireTime;
@Override
public String toString()
return "CalcResult" +
"effectTime=" + effectTime +
", expireTime=" + expireTime +
'';
Test:
public class EffectExpireTest
public static void main(String[] args)
CalcRequest input = new CalcRequest();
input.setCreateTime(1L);
AbstractEffectExpireCalc calc = new RegularEnvCalc();
CalcResult result = calc.calc(input);
System.out.println("常温环境保质期:" + result.getEffectTime() + "-" + result.getExpireTime());
calc = new ColdEnvCalc();
result = calc.calc(input);
System.out.println("寒冷环境保质期:" + result.getEffectTime() + "-" + result.getExpireTime());
优化
模板模式不是很复杂,但是运用中有个小缺点,如果子类实现很多,那就会造成子类的泛滥。针对这种场景,有大佬提出了解决方法,通过传入回调函数原本有子类实现的具体流程。
EffectExpireCalc:
public class EffectExpireCalc
public CalcResult calc(CalcRequest input, PrepareCalcCallBack prepareAction, SpecicalCalcCallBack specialAction)
CalcRequest inputCanbeUse = input;
// 预处理产品的生产日期
prepareAction.prepareCalc(inputCanbeUse);
// 常规计算
CalcResult result = regularClac(inputCanbeUse);
// 不同存储条件下计算产品保质期
specialAction.specicalCalc(inputCanbeUse, result);
return result;
private CalcResult regularClac(CalcRequest inputCanbeUse)
CalcResult result = new CalcResult();
result.setEffectTime(inputCanbeUse.getCreateTime());
return result;
PrepareCalcCallBack :
public interface PrepareCalcCallBack
void prepareCalc(CalcRequest inputCanbeUse);
SpecicalCalcCallBack :
public interface SpecicalCalcCallBack
void specicalCalc(CalcRequest inputCanbeUse, CalcResult result);
Test:
public class EffectExpireTest
public static void main(String[] args)
CalcRequest input = new CalcRequest();
input.setCreateTime(1L);
EffectExpireCalc calc = new EffectExpireCalc();
CalcResult result = calc.calc(input, new PrepareCalcCallBack()
@Override
public void prepareCalc(CalcRequest inputCanbeUse)
System.out.println("常温环境-不做预处理");
, new SpecicalCalcCallBack()
@Override
public void specicalCalc(CalcRequest inputCanbeUse, CalcResult result)
result.setExpireTime(inputCanbeUse.getCreateTime() + 10000);
);
System.out.println("常温环境保质期:" + result.getEffectTime() + "-" + result.getExpireTime());
result = calc.calc(input, new PrepareCalcCallBack()
@Override
public void prepareCalc(CalcRequest inputCanbeUse)
System.out.println("寒冷环境-不做预处理");
, new SpecicalCalcCallBack()
@Override
public void specicalCalc(CalcRequest inputCanbeUse, CalcResult result)
result.setExpireTime(inputCanbeUse.getCreateTime()+ 20000);
);
System.out.println("寒冷环境保质期:" + result.getEffectTime() + "-" + result.getExpireTime());
可以看出虽然回调函数减少了子类泛滥,但是该写的代码还是没少啥,关键是结构没有用子类实现那么清晰了,所以用的时候也要权衡下。
以上是关于设计模式-模板的主要内容,如果未能解决你的问题,请参考以下文章
生鲜行业数字化采购管理系统:助力生鲜企业解决采购难题,全程线上化采购执行