“Head First 设计模式“ :模板方法模式

模板方法模式


定义:模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。模板方法就是一个固定步骤的“算法”骨架方法。这个算法的可变部分通过继承,在子类中重载实现。这样就可以在算法骨架不变的情况下,算法细节步骤根据不同的需求进行适应的改变,类图如下:
“Head First 设计模式“ :模板方法模式


优点
● 模板方法模式在定义了一组算法,将具体的实现交由子类负责。
● 模板方法模式是一种代码复用的基本技术。
● 模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。


缺点
● 每一个不同的实现都需要一个子类来实现,导致类的个数增加,是的系统更加庞大。


使用场景
● 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
● 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
● 控制子类的扩展。


案例1:泡茶,泡咖啡有好多共同步骤,如下:
● 煮沸水
● 加入茶叶冲泡(咖啡粉)
● 根据需求加入调料(如蜂蜜、柠檬,糖)
● 将泡好的茶水倒入杯子
泡茶代码如下(咖啡也类似,所以省略了哦):

public class Tea {
   // 执行步骤
   void prepareRecipe() {
      boilWater();
      steepTeaBag();
      pourInCup();
      addLemon();
   }
   public void boilWater() { System.out.println("Boiling water");}
   public void steepTeaBag() {System.out.println("Steeping the tea"); }
   public void addLemon() { System.out.println("Adding Lemon"); }
   public void pourInCup() { System.out.println("Pouring into cup");}
}

我们不难发现这两个类中代码重复了很多,步骤一样,我们可以封装起来,我们用模板方法模式来修改,如下:
模板方法代码:

public abstract class CaffeineBeverage {
   final void prepareRecipe() {
      boilWater();
      brew();
      pourInCup();
      addCondiments();
   }
   abstract void brew();
   abstract void addCondiments();
   void boilWater() {
      System.out.println("Boiling water");
   }
   void pourInCup() {
      System.out.println("Pouring into cup");
   }
}

泡茶代码:

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

总结:子类可以灵活实现每个步骤的具体逻辑,执行步骤用抽象类里的prepareRecipe()方法决定。


案例2:钩子的使用,钩子就是一个boolean状态,控制prepareRecipe()里是否需要执行某个步骤代码(子类自行修改),如下:

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;
   }
}

Java中的模板方法模式:
● Applet
● Swing里的JFrame
● java.io.InputStream, java.io.OutputStream, java.io.Reader 以及 java.io.Writer 中所有非抽象方法。
● java.util.AbstractList, java.util.AbstractSet 以及 java.util.AbstractMap中所有非抽象方法。


设计原则:好菜鸟原则,不要找我们,我们会找你的。

猜你喜欢

转载自blog.51cto.com/u2r2otkit/2108487