设计模式-模板

场景

模板模式适合:父类控制业务处理流程,子类负责业务逻辑具体处理逻辑,换一种说法就是父类控制算法主流程,子类实现个性化步骤。典型案例就是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());
    }
}

可以看出虽然回调函数减少了子类泛滥,但是该写的代码还是没少啥,关键是结构没有用子类实现那么清晰了,所以用的时候也要权衡下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值