思想
模板方法模式很容易理解。思想基本如下:先在父类规定了具体的算法步骤以及算法顺序。父类可以给出部分步骤的具体实现,也可以都只给出方法框架,没有具体实现。在子类具体实现各个步骤的方法,但是各个步骤间的顺序在父类已经确定,子类无法通常不应该更改。如果规定算法顺序的方法在父类被定义成final,则子类就无法更改了。具体实现,根据实际需求确定。
。其目的一方面是减少代码重复,达到代码复用的目的
。另一方面也可以在父类控制和限制子类的动作。
。父类(泛化类)规定了一个算法框架,大多数时候,只要修改子类即可。
。将具体算法和实现相分离,各司其职(单一职责),基类负责算法设计,(某些情况也会涉及一点实际实现),子类专司具体算法实现。
咖啡因饮料代码实现
CaffeineBeverageWithHook.Java
package judge; public abstract class CaffeineBeverageWithHook { public void prepareRecipe(){ //此处若定义为final类可防止子类改变它的顺序 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; } }
CoffeeWithHook.Java
package judge; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import javax.swing.plaf.basic.BasicInternalFrameTitlePane.IconifyAction; public class CoffeeWithHook extends CaffeineBeverageWithHook{ @Override void brew() { // TODO Auto-generated method stub System.out.println("Dripping Coffee"); } @Override void addCondiments() { // TODO Auto-generated method stub System.out.println("Adding Sugar"); } @Override boolean customerWantsCondiments() { //覆盖钩子 // TODO Auto-generated method stub String answer = getUserInput(); if(answer.toLowerCase().startsWith("y")){ return true; } else { return false; } } private String getUserInput (){ String answer = null; System.out.println("would you like milk? (y/n)"); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); try { answer = in.readLine(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (answer == null) { return "no"; } return answer; } }
扫描二维码关注公众号,回复:
8009426 查看本文章
Test.Java
package testJudge; import judge.CoffeeWithHook; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub CoffeeWithHook coffeeWithHook = new CoffeeWithHook(); coffeeWithHook.prepareRecipe(); } }
总结
我们有两个重要的部分,一个是抽象基类,一个是具体子类。
在抽象基类中我们要提供基本方法,抽象方法,钩子函数(可选)以及模板方法(final)。
在具体子类中我们要实现基类中的抽象方法,可选的钩子方法
模板方法就是准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模板方法。
适用场景
1.算法或操作遵循相似的逻辑
2.重要、复杂的算法,核心算法设计为模板算法
优点和缺点
优点
1.封装性好
2.复用性高
3.屏蔽细节
4.便于维护
缺点:继承的唯一性