• 模板方法模式


    1.定义

    在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 简单来说就是抽象类中的一个 final 修饰的 方法封装了几个方法,而这些方法需要子类的具体实现,但是总体算法的步骤是抽象类中定义好的.

    2.代码实现

    这次模拟的是泡咖啡和泡茶两种行为,泡咖啡的步骤是 1.烧开水 2.冲泡咖啡粉 3. 咖啡倒进杯子 4. 加糖和牛奶

    泡茶的步骤是 1.烧开水 2. 泡茶叶 3. 把茶倒进杯子 4. 加柠檬

    这边相似的动作是 1 烧开水 和 3 倒进杯子  不同的是 一个泡的咖啡,加的是糖和牛奶,另一个是 泡的茶,加的是柠檬. 所以我们可以把 冲泡这个动作和加东西这个动作给抽象出来,具体的实现让子类进行.

    这两种行为的步骤都是一致的,所以我们可以用一个抽象类来封装这种步骤.

    public abstract class CaffeineBeverage {
        
        /**
         * 封装的步骤
         */
        final void prepareRecipe() {
            boilWater();
            brew();
            pourInCup();
            if (customerWantsCondiments()) {
                addCondiments();
            }
        }
        
        abstract void brew();
        abstract void addCondiments();
        
        void boilWater() {
            System.out.println("Biling water");
        }
        
        void pourInCup() {
            System.out.println("Pouring into cup");
        }
        /**
         * 钩子方法
         * @return
         */
        boolean customerWantsCondiments() {
            return true;
        }
        
    }

    prepareRecipe 这个方法中 ,我们调用了 烧开水,冲泡,倒进杯子,加调料这四种方法,其中烧开水和倒进杯子这两种方法由抽象类实现,因为都是冲泡饮料相同的动作,不同的实现冲泡和加调料这两种方法,我们可以让具体的子类去实现. 而且prepareRecipe 方法是final类型的,就是防止子类覆盖这个方法修改方法的执行步骤.

    customerWantsCondiments 方法是钩子方法,钩子方法在模板方法中可以当作一个条件来让子类决定算法的行为,子类可以选择实现或者选择不实现.

    我们先定义茶

    public class Tea extends CaffeineBeverage{
    
        @Override
        void brew() {
            System.out.println("Steeping the tea");
        }
    
        @Override
        void addCondiments() {
            System.out.println("Adding Lemon");
        }
    }

    茶这边实现了咖啡饮料这个抽象方法, 并且实现了 brew 和 addCondiments 这里两种抽象方法.

    定义咖啡

    public class Coffee extends CaffeineBeverage{
    
        @Override
        void brew() {
            System.out.println("Dripping Coffee through filter");
        }
    
        @Override
        void addCondiments() {
            System.out.println("Adding sugar and milk");
        }
    
        @Override
        boolean customerWantsCondiments() {
            Scanner sc = new Scanner(System.in);
            String str = sc.nextLine();
            
            if (str.toLowerCase().equals("y")) {
                return true;
            }
            
            return false;
        }
        
        
    }

    咖啡也实现了 brew 和 addCondiments 这里两种抽象方法. 并且也实现了customerWantsCondiments方法,可以通过舒服 'Y' 或者 'N' 来让用户选择加糖和牛奶或者不加.这就是钩子的一个用途.

    测试累

    public class ModelTest {
        public static void main(String[] args) {
            Tea tea = new Tea();
            tea.prepareRecipe();
            
            System.out.println();
            
            Coffee coffee = new Coffee();
            coffee.prepareRecipe();
        }
    }

    执行结果

    Biling water
    Steeping the tea
    Pouring into cup
    Adding Lemon
    
    Biling water
    Dripping Coffee through filter
    Pouring into cup
    Y
    Adding sugar and milk

    这里输入了 Y 以后才加入了Adding Sugar and mikl

    3.总结

    我们可以看到模板方法主要是通过继承来实现的,在抽象类中定义了一个final方法来规定算法的具体框架,然后算法框架中的具体实现让子类去进行,所以这种需要子类实现的算法可以定义成 abstract 类型.

    这里钩子这个方法因为是子类可以选择实现或者选择不实现的方法,所以没必要定义成abstract类型,主要是用来让子类实现这个方法改变算法的一些步骤.

    和策略模式不同的是,模板方法是定义算法的框架,而策略模式是通过组合的方式来实现具体的算法.两者定位不同.

    这边工厂模式也是通过子类来决定具体生成哪一种工厂模式,并且也是通过继承抽象类的方法来实现,所以也可以把工厂模式当作模板方法的变体.

  • 相关阅读:
    CSS概述
    CSS基础
    CSS定位与布局
    CSS动画,2D和3D模块
    第一硬汉左宗棠死了,晚清再无脊梁!
    南怀瑾老师:读书万卷,神交古人
    左宗棠读书修身8句,神交古人
    神交古人
    心忧天下,神交古人
    ECCV 2016 paper list
  • 原文地址:https://www.cnblogs.com/lishuaiqi/p/11241560.html
Copyright © 2020-2023  润新知