模板方法模式——HeadFirst设计模式学习笔记

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

    • 模板就是基类中的一个方法,包含一组步骤,任何一个步骤都可以是抽象的,可以在保证算法结构不变的情况下由子类实现具体某个步骤

类图:

 

特点:

  • 模板方法定义了一算法的步骤,并允许子类为一个或多个步骤提供实现
  • 基类主导一切,它拥有这个算法,知道这个算法的执行步骤,并保护这个算法,基类关在与算法本身步骤,而由子类提供完整实现
  • 算法只存在于基类便于修改,算法中相同的部分由基类实现,将代码复用最大化
  • 模板方法的抽象类可以定义具体方法(final)、抽象方法、钩子

注意:

  • 模板方法应该被定义为final,以防止被子类覆盖
  • 模板方法中具体某一步也可以定义为final,以防止被子类覆盖

默认不做事情的方法hook:

  • 只有空或者默认的实现,子类可以自行决定是否覆盖
  • 可以用作条件控制,影响抽象类中算法的流程
  • 子类必须实现时使用抽象方法,是否实现可选时使用hook方法

好莱坞原则:别调用我们,我们会调用你

  • 允许底层组件自己挂钩到系统上,但是什么时候使用怎么使用这些组建由高层组建决定
  • 好莱坞原则vs依赖倒置原则
    • 依赖倒置原则教我们避免使用具体的类,使用接口抽象编程
    • 好莱坞原则运用在框架上,底层组件依靠挂钩参与运算,但又不会让高层组建依赖于底层组建
    • 两者的目的均是解耦、避免依赖,创造有弹性的设计

JavaAPI中应用

  • Arrays.sort()函数通过被排序数组对象的compareTo()函数填补模板方法的比较方法

模板方法模式vs策略模式:

  • 策略使用组合,模板方法使用继承
  • 策略定义算法家族,算法可以相互替换;模板方法定义算法大纲,具体步骤细节可以在子类实现

举例:

制作咖啡因饮品的模板方法基类

 1 public abstract class CaffeineBeverage {  
 2     
 3     final void prepareRecipe() {  
 4         boilWater();//把水煮沸  
 5         brew();//用热水泡咖啡或茶  
 6         pourInCup();//把饮料(咖啡或茶)倒进杯子  
 7         addCondiments();//加入调料  
 8     }  
 9    
10     abstract void brew();  
11     
12     abstract void addCondiments();  
13    
14     void boilWater() {  
15         System.out.println("Boiling water");  
16     }  
17     
18     void pourInCup() {  
19         System.out.println("Pouring into cup");  
20     }  
21 } 

Coffee实现

1 public class Coffee extends CaffeineBeverage {  
2     public void brew() {  
3         System.out.println("Dripping Coffee through filter");  
4     }  
5     public void addCondiments() {  
6         System.out.println("Adding Sugar and Milk");  
7     }  
8 }  

使用钩子的模板方法

 1 void prepareRecipe() {  
 2     boilWater();  
 3     brew();  
 4     pourInCup();  
 5     //让子类可以决定算法是否执行该步骤  
 6     //customerWantsCondiments()方法是一个钩子,父类对其其默认实现返回true,即默认执行步骤(4)  
 7     if (customerWantsCondiments()) {  
 8         addCondiments();  
 9     }  
10 }  

咖啡类钩方法实现

 1     public boolean customerWantsCondiments() {  
 2   
 3         String answer = getUserInput();  
 4   
 5         if (answer.toLowerCase().startsWith("y")) {  
 6             return true;  
 7         } else {  
 8             return false;  
 9         }  
10     }  
原文地址:https://www.cnblogs.com/HectorHou/p/6001073.html