参考书籍:Head First设计模式
什么是模板方法模式
定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
怎么理解这个定义呢?个人觉得这个定义主要有三个核心的点:
- 算法的骨架
- 步骤延迟到子类
- 子类在不改变算法结构的情况下,重新定义算法的某些步骤
什么是算法的骨架?
设计模式中举的例子是咖啡和茶的例子。冲泡咖啡和茶的流程如下:
冲泡咖啡步骤:把水煮沸----->用沸水冲泡咖啡----->把咖啡倒进杯子----->加糖和牛奶
冲泡茶步骤:
把水煮沸----->用沸水浸泡茶叶----->把茶倒进杯子----->加柠檬
仔细观察两种方式,发现咖啡和茶的冲泡法大致相同。这时候可以提炼(抽象)出一个冲泡饮品的流程出来,具体流程如下:(好比把大象装进冰箱要三步:1、把冰箱门打开2、把大象塞进去3、关上冰箱门)。
冲泡饮品:把水煮沸----->用热水泡饮品----->把饮料倒进杯子----->在饮料内加入适量的调料
我们把抽象出来的流程放进一个抽象类中供其子类(咖啡、茶等)使用,这个冲泡饮品的流程就可以称作为 算法的骨架。一般在抽象类中的表现形式如下:骨架方法 定义为final
1 package tudou.javabasic.clone; 2 3 /** 4 * Created by tudou on 2017-02-23. 5 */ 6 public abstract class CaffieineBeverage { 7 final void prepareRecipe(){ 8 boilWater(); 9 brew(); 10 pourInCup(); 11 addCondiments(); 12 } 13 14 protected abstract void addCondiments(); 15 16 private void pourInCup() { 17 } 18 19 protected abstract void brew(); 20 21 private void boilWater() { 22 } 23 }
步骤延迟到子类
抽象类中只是对要操作的步骤进行了抽象,并没有全部去具体实现。相同的部分可以实现,例如:把饮品导入杯中(pourInCup)。不同的部分通过具体子类继承来单独实现。
重新定义算法的骨架-使用钩子
钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。
有了钩子,子类能够决定要不要覆盖方法,如果不提供自己的方法,抽象类会提供一个默认的实现。
例如:Swing窗口程序中的钩子:paint()方法。在默认情况下paint()方法是不做事情的(即空实现)(JFrame的超类Component中对paint()进行了空实现),它是一个“钩子”,通过覆盖paint()方法,我们可以将自己的代码插入到JFrame的算法中,显示出想要的画面。
1 public class MyFrame extends JFrame 2 { 3 public MyFrame(String titile) 4 { 5 super(titile); 6 this.setDefaultCloseOperation(EXIT_ON_CLOSE); 7 this.setSize(200, 200); 8 this.setVisible(true); 9 } 10 11 @Override 12 public void paint(Graphics g) 13 { 14 super.paint(g); 15 g.drawString("paint() is a hook", 40, 100); 16 } 17 18 public static void main(String[] args) 19 { 20 MyFrame f = new MyFrame("swing"); 21 } 22 }
效果如下: