Template

    xiaoxiao2021-03-25  183

    模板方法(Template Method)

    模板方法模式——在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

    原则

    好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。 (封装算法块)

    类图

    Code

    origin

    // 这是我们的咖啡类,用来煮咖啡 public class Coffee { // 这是我们的咖啡冲泡法 void prepareRecipe() { boilWater(); brewCoffeeGrinds(); pourInCup(); addSugerAndMilk(); } // 煮沸水 private void boilWater() { System.out.println("Boiling water"); } // 冲泡咖啡 private void brewCoffeeGrinds() { System.out.println("Dripping coffee through filter"); } // 把咖啡倒进杯子 private void pourInCup() { System.out.println("Pouring into cup"); } // 加糖和奶 private void addSugerAndMilk() { System.out.println("Adding Sugar and Milk"); } } // 这是我们的茶类,用来煮茶 public class Tea { void prepareRecipe() { boilWater(); steepTeaBag(); pourInCup(); addLemon(); } // 煮沸水。这个方法和咖啡类完全一样 private void boilWater() { System.out.println("Boiling water"); } // 冲泡茶叶 private void steepTeaBag() { System.out.println("Steeping the tea"); } // 把茶倒进杯子。这个方法和咖啡类完全一样 private void pourInCup() { System.out.println("Pouring into cup"); } // 加柠檬 private void addLemon() { System.out.println("Adding Lemon"); } }

    改进

    public abstract class CaffeineBeverage { // 现在,用同一个prepareRecipe()方法来处理茶和咖啡。 // prepareRecipe()方法被声明为final,因为我们不希望子类覆盖这个方法 // 我们将第2步和第4步泛化成为brew()和addCondiments() final void prepareRecipe() { boilWater(); brew(); pourInCup(); addCondiments(); } // 因为咖啡和茶处理这些方法的做法不同,所以这两个方法必须被声明为抽象, // 剩余的东西留给子类去操心 abstract void addCondiments(); abstract void brew(); public void boilWater() { System.out.println("Boiling water"); } public void pourInCup() { System.out.println("Pouring into cup"); } } // 自行处理冲泡和添加调料部分: 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"); } } public class Tea extends CaffeineBeverage { @Override void brew() { System.out.println("Steeping the tea"); } @Override void addCondiments() { System.out.println("Adding Lemon"); } }

    模板方法

    // 这就是我们的抽象类。它被声明为抽象,用来作为基类,其子类必须实现其操作 public abstract class AbstractClass { // 这就是模板方法。它被声明为final,以免子类改变这个算法的顺序。 final void templateMethod() { // 模板方法定义了一连串的步骤,每个步骤由一个方法代表 primitiveOperation1(); primitiveOperation2(); concreteOperation(); } // 在这个范例中有两个原语操作,具体子类必须实现它们 abstract void primitiveOperation1(); abstract void primitiveOperation2(); // 这个抽象类有一个具体的操作。 void concreteOperation() { // ... } }

    钩子

    public abstract class AbstractClass { final void templateMethod() { primitiveOperation1(); primitiveOperation2(); concreteOperation(); // 我们加进一个新方法调用 hook(); } // 这两个方法还是和以前一样,定义成抽象,由具体的子类实现。 abstract void primitiveOperation1(); abstract void primitiveOperation2(); // 这个具体的方法被定义在抽象类中。 // 将它声明为final,这样一来子类就无法覆盖它。 // 它可以被模板方法直接使用,或者被子类使用。 final void concreteOperation() { // ... } // 我们也可以有“默认不做事的方法”,我们称这种方法为“hook”(钩子)。 // 子类可以视情况决定要不要覆盖它们。在下面,我们就会知道钩子的实际用途 void hook() {} }

    Reference

    http://cashow.github.io/head-first-design-patterns-notes-template-method-pattern.html

    转载请注明原文地址: https://ju.6miu.com/read-1395.html

    最新回复(0)