定义一个模板抽象类,算法固定,个别函数抽象,可以在不改变算法结构的情况下在子类中重新定义算法的步骤。

我们来看看这个抽象类如何定义:

 Abstract class AbstractClass {

   Abstract void primitiveOperation1(); //继承后可修改具体实现

   Abstract void primitiveOperation2();

   Void concreteOperation(){  //被所有子类或模板方法直接调用的方法;

   }

   Final void templateOperation(){  //模板方法,整个算法结构以及功能固定;

     primitiveOperation1();

     primitiveOperation2();

     concreteOperation();

   }

   Void hook(){  //留给子类的继承接口,可用来增加自己对算法的条件修改;我们叫做钩子

}

 

}

我们看一下例子:泡咖啡和冲饮料基本步骤都是一样的,只是每个步骤地操作不同,我们用模板方法模式来实现:

public abstract class CaffeineBeverageWithHook {

      void prepareRecipe() {

              boilWater();

              brew();

              pourInCup();

              if (customerWantsCondiments()) {

                     addCondiments();

              }

       }

    //整体步骤

      abstract void brew();

      abstract void addCondiments();

    //子类继承后实现

      void boilWater() {

              System.out.println("Boiling water");

       }

      void pourInCup() {

              System.out.println("Pouring into cup");

       }

    //子类共有覆盖

      boolean customerWantsCondiments() {

              return true;

       }

     //hook函数,子类可覆盖

}

我们来看看如何泡咖啡:

public class Coffee extends CaffeineBeverageWithHook {

      public void brew() {

              System.out.println("Dripping Coffee through filter");

       }

      public void addCondiments() {

              System.out.println("Adding Sugar and Milk");

       }

      public boolean customerWantsCondiments() {

              String answer = getUserInput();

              if (answer.toLowerCase().startsWith("y")) {

                     return true;

              } else {

                     return false;

              }

       }

       private String getUserInput() {

              String answer = null;

              System.out.print("Would you like milk and sugar with your coffee (y/n)? ");

              BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

              try {

                     answer = in.readLine();

              } catch (IOException ioe) {

                     System.err.println("IO error trying to read your answer");

              }

              if (answer == null) {

                     return "no";

              }

              return answer;

       }

}

我们看到 覆盖了customerWantsCondiments.增加了与用户确定调料的判断.这就是钩子的作用;

我们来写了测试类:

       public static void main(String[] args) {

             Coffee coffee = new Coffee();

             System.out.println("\nMaking coffee...");

              coffee.prepareRecipe();

       }

}

同样可以在写个TEA类继承CaffeineBeverageWithHook,实现同Coffee

我们在延伸一下:

JFrame,Applet都是模板模式,定义了整个生命周期,我们在开始时总是这样:

public class MyApplet extends Applet{}去实现各个生命周期的方法。

 

模板方法和策略方法的比较:

相同点:二者都是提供算法

不同:模板使用继承,策略使用组合,利用接口;

工厂方法是模版方法的一种情况,还记得吗?

Public Abstract class FactoryMethod{

   Abstract void createFactory();

  

   void FactoryMethodOperation(){  //模板方法,整个算法结构以及功能固定;

 

   }

}

工厂方法将实例的创建推迟到子类中。