设计模式-模板方法

template method模式:将部分的特殊实现交给子类

场景:

(1) 我们有多种优惠策略

(2) 不同的优惠策略在计算价格的时候,有一些是通用的基础逻辑

(3) 然后,每种优惠策略 还有一些是自己 比较特殊的价格计算的逻辑

不用模板方法的代码实现:

我们比如说,有3中优惠的方式,

第一种折扣计算器类DiscountCalculator1,里面有方法calculate,方法实现 有一个通用的计算逻辑,还有优惠计算器1的特殊计算逻辑;

分别还有,

第二种折扣计算器类DiscountCalculator2,里面有方法calculate,方法实现 有一个通用的计算逻辑,还有优惠计算器2的特殊计算逻辑;

第二种折扣计算器类DiscountCalculator3,里面有方法calculate,方法实现 有一个通用的计算逻辑,还有优惠计算器3的特殊计算逻辑;

然后,我们在main方法中去调用它们,

    public static void main(String[] args) {
        DiscountCalculator1 calculator1 = new DiscountCalculator1();
        calculator1.calculate();

        DiscountCalculator2 calculator2 = new DiscountCalculator2();
        calculator2.calculate();

        DiscountCalculator3 calculator3 = new DiscountCalculator3();
        calculator3.calculate();
    }

输出如下:

通用的计算逻辑
优惠计算器1的特殊计算逻辑
通用的计算逻辑
优惠计算器2的特殊计算逻辑
通用的计算逻辑
优惠计算器3的特殊计算逻辑

Process finished with exit code 0

那么这里,如果不用设计模式的话,有一个问题,就是说 这个三种优惠方式计算器里面,都有一段通用计算逻辑,其实是完全相同的代码,但是完全相同的一段代码,给通过复制粘贴的方式,放到了不同的类里去,那么一旦说,那个通用的计算的计算逻辑 要修改,就涉及到多个类都要去修改那个代码,如果你一旦忘了修改某个类中的那段代码,后果不堪设想;而且到了后期,几乎没人记得清楚,那段通用逻辑代码放在了多少个类中,如果要排查,需要将很多类重新读一遍代码,这就是垃圾代码,扩展性,维护性,很烂。所以这个情况下,我们必须要用设计模式。

使用模板方法的代码实现:

这个时候,我们要这么来玩,

我们先定义一个接口DiscountCalculator,这个接口中定义了一个方法void calculate()即可。当然,这个接口肯定是要定义的,因为我们要面向接口去开发的嘛!

然后,定义一个抽象类作为基础类AbstractDiscountCalculator implement DiscountCalculator,

在抽象的基础类中,定义一个方法private void commonCalculate(),其中封装了一段通用的计算逻辑;

还有一个protected abstract void specificCalculate();,这个是没有实现的,因为它是一个抽象方法;

最后,还要重写接口中的对外提供的调用方法public void calculate(),其中,先执行commonCalculate()这段通用的计算逻辑,再执行特殊的计算逻辑specificCalculate();

那么,在具体的实现类中,比如DiscountCalculator1 extends AbstractDiscountCalculator,我们只需实现父类中抽象方法speificCalculate()的具体实现逻辑,优惠计算器1的特殊计算逻辑即可。

代码如下:

public class TemplateMethodPatternDemo {

    public static void main(String[] args) {
        DiscountCalculator calculator1 = new DiscountCalculator1();
        calculator1.calculate();

        DiscountCalculator calculator2 = new DiscountCalculator2();
        calculator2.calculate();

        DiscountCalculator calculator3 = new DiscountCalculator3();
        calculator3.calculate();
    }

    public interface DiscountCalculator {
        void calculate();
    }

    /**
     * 模板方法实现的精华所在
     */
    public static abstract class AbstractDiscountCalculator implements DiscountCalculator {

        public void calculate(){
            // 完成通用的计算逻辑
            commonCalculate();
            // 完成特殊的计算逻辑
            specificCalculate();
        }

        private void commonCalculate(){
            System.out.println("通用的计算逻辑");
        }

        protected abstract void specificCalculate();
    }

    public static class DiscountCalculator1 extends AbstractDiscountCalculator{
        public void specificCalculate(){
            System.out.println("优惠计算器1的特殊计算逻辑");
        }
    }

    public static class DiscountCalculator2 extends AbstractDiscountCalculator{
        public void  specificCalculate(){
            System.out.println("优惠计算器2的特殊计算逻辑");
        }
    }

    public static class DiscountCalculator3 extends AbstractDiscountCalculator{
        public void  specificCalculate(){
            System.out.println("优惠计算器3的特殊计算逻辑");
        }
    }

}

在这里面的很好的设计就是,通用的计算逻辑,全部给抽出来放在抽象父类AbstractDiscountcalculator中的commonCalculate()方法这个地方,然后,特殊的计算逻辑,定义成抽象方法specificCalculate(),父类不实现,交给子类,比如DiscountCalculator1 extends AbstractDiscountCalculator,子类继承父类之后,子类里面去覆盖实现父类中的这个特殊的计算逻辑。这样的话,对于不同策略优惠的计算器来说,它们通用的计算逻辑没有重复在各个具体的实现中,而是抽取到抽象的父类里面去了,只有这么一块;然后每个子类里面分别去实现自己自己特殊的计算逻辑即可。而这个时候,我们如果要把通用的计算逻辑修改一下,只需要在抽象的父类这一个类里面修改就可以了,也就是说,模板方法这个模式,就是把多个类里面 通用的逻辑 抽象到一个抽象父类里面去,然后,再在各个子类里面去实现它们特有的一个逻辑,在抽象父类里面,对外提供的方法,会定义清楚什么时候去执行通用的计算逻辑,什么时候去执行这个特殊的计算逻辑,特殊的计算逻辑这个方法,是给定义成抽象方法,留给子类去覆盖的,这样就通过模板方法模式,定义一个抽象方法,完美解决了重复性代码的问题。

 总结:

模板方法设计模式,这个应该是,最高频使用的设计模式,这个高频到了,我都不用在这里举个什么例子,因为在任何一个系统中,一定会出现说,多个类中,其实都有相同的代码,此时就可以使用模板方法设计模式,然后将多个类中通用的设计模式,抽取到一个父类中去。那么什么叫做模板方法呢,其实就是父类里面定义成抽象方法,就是所谓的模板方法,因为这个需要子类去具体实现抽象的方法,只是一个模板,它并没有实现,模板的实现是通过子类去实现的。

 

end

posted @ 2022-06-16 12:05  HarryVan  阅读(28)  评论(0编辑  收藏  举报