设计模式-模板

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());
    

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

以上是关于设计模式-模板的主要内容,如果未能解决你的问题,请参考以下文章

划得来模式

生鲜行业数字化采购管理系统:助力生鲜企业解决采购难题,全程线上化采购执行

生鲜行业数字化采购管理系统:助力生鲜企业解决采购难题,全程线上化采购执行

保质期项目数据库更改

如何查询Lancome生产及保质期

技术的保质期越来越短