模板方法模式

来源:互联网 发布:流行朋克知乎 编辑:程序博客网 时间:2023/12/03 10:01

定义

    在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
    通俗理解就是:在一个基类里面,定义了一个算法的流程(里面调用了很多方法),其中一些方法是基类已经实现的,一些是需要具体子类或实现类来实现的,还有一下是钩子(允许子类或实现类重写,如果不重写就按默认的执行),那么那个基类的流程方法就是模板方法。即算法框架的轨迹已经定义好了,部分实现允许按实际情况自己定义。模块方法模式在框架的架构中大量使用。

生活案例

    在一个饮料冲泡的流程中,对于不同的饮料,很多方法都是相同的,只有部分实现是根据不同的饮料来实现的。所以可以定义一个基类:(prepareRecipe()为模板方法)
其中boilWater()和pourInCup()是每种饮料都需要的,所以基类来实现这两种方法,brew()和addCondiments()是根据不同饮料来实现的,所以定义为抽象类,需要子类来实现。

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 Coffee extends CaffeineBeverage {public void brew() {System.out.println("Dripping Coffee through filter");}public void addCondiments() {System.out.println("Adding Sugar and Milk");}}

    钩子的定义:钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。  
    所以在饮料冲泡的流程中,对于要不要加入调料(即addCondiments)应该可以选择。
所以修改后的基类是:
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;}}

咖啡类:
public class CoffeeWithHook 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;}}

    这样就可以让顾客自行选择要不要调料了,最重要的是这样使得了框架更灵活了,可以选择是否执行某个步骤,而不是按照一个死的流程来走。

java API中使用到的模板方法模式

    这个是Arrays的sort()方法(就是排序功能),注意,这个例子里面没有用到像上面那个例子的抽象父类,而是用了一个静态方法(在这里也就是模板方法),这个静态方法有调用了本类的方法(即基类已经实现好的方法),也有调用需要实现类(这里不是子类了,而是接口的实现类)实现的方法。所以整个sort()流程的框架是定义好的,需要的是根据不同的实现类来实现部分具体的方法。
    部分Arrays的源码:
 public static void sort(Object[] a) {        Object[] aux = (Object[])a.clone();        mergeSort(aux, a, 0, a.length, 0);    }private static void mergeSort(Object[] src,  Object[] dest,  int low,  int high,  int off) {int length = high - low;// Insertion sort on smallest arrays        if (length < INSERTIONSORT_THRESHOLD) {            for (int i=low; i<high; i++)                for (int j=i; j>low && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)                    swap(dest, j, j-1);            return;        }

其中compareTo()方法是需要具体实现类来实现的,其他是基类Arrays已经实现的(有些常量和方法没贴出来,读者可以自行看java源码)。
    那么具体实现类是怎样的:
public class Duck implements Comparable {String name;int weight;  public Duck(String name, int weight) {this.name = name;this.weight = weight;} public String toString() {return name + " weighs " + weight;}    public int compareTo(Object object) { Duck otherDuck = (Duck)object;  if (this.weight < otherDuck.weight) {return -1;} else if (this.weight == otherDuck.weight) {return 0;} else { // this.weight > otherDuck.weightreturn 1;}}}

具体实现类需要实现Comparable接口,因为在基类算法流程里面需要将这个类强转为Comparable类型;具体实现类也需要实现compareTo()这个方法,流程里面也需要调用这个方法(即部分需要根据具体实现类来实现的方法)。
    这样鸭子的排序流程就可以顺利进行了。

    模板方法模式整体就是这样,大家如果有什么想法想交流交流,欢迎在下面评论哦。微笑

5 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怕闺蜜比我好怎么办 孩子不会做应用题怎么办 当你嫉妒别人怎么办 单位社保发票丢失怎么办 单位医保发票丢失怎么办 图书明细没有给怎么办 拼音拼不到一起怎么办 孩子不会拼拼音怎么办 小孩子不会拼拼音怎么办 小孩拼音发音不准怎么办 孩子声调不会标怎么办 孩子拼音发音不准怎么办 孩子学拼音不会怎么办? 孩子不会拼生字怎么办? 对数字不敏感怎么办 孩子说话不算数怎么办 儿童做事不认真怎么办 幼儿园小朋友爱打人怎么办 遇到熊孩子家长怎么办 小孩嘴烂了怎么办 孩子杯宠坏了怎么办 小孩子老爱打人怎么办 小孩偏执的性格怎么办 孩子上学爱打人怎么办 宝宝爱动手打人怎么办 幼儿爱打人教师怎么办 中班幼儿爱打人怎么办 幼儿园小班小朋友打人老师怎么办 2岁小朋友打人怎么办 幼儿爱乱讲话怎么办 幼儿园小孩打架老师怎么办 宝宝不自信胆小怎么办 小孩不尊重父母怎么办 孩子有洁癖应该怎么办 宝宝攻击性太弱怎么办 小孩在幼儿园打人怎么办 小孩说老师打人怎么办 孩子总动手打人怎么办 辅导小孩老发火怎么办 孩子喜欢咬人怎么办 小孩见家人不叫怎么办