模板方法模式

来源:互联网 发布:js压缩还原工具 编辑:程序博客网 时间:2024/05/22 10:35
【0】README
0.1)本文部分描述转自 “head first设计模式”,旨在学习 模板方法模式 的基础知识;

【1】看个荔枝——星巴克咖啡
1.1)星巴克咖啡冲泡法steps:
step1)把水煮沸;
step2)用沸水冲泡咖啡;
step3)把咖啡倒进杯子;
step4)加糖和牛奶;
1.2)星巴克茶冲泡法steps:
step1)把水煮沸;
step2)用沸水浸泡茶叶;
step3)把茶倒进杯子;
step4)加柠檬;
2)对以上问题的分析(Analysis)
A0)上述两种泡法都采用了相同的算法:
step1)把水煮沸;
step2)用热水泡咖啡或者茶;
step3)将饮料倒进杯子;
step4)在饮料内加入适当的调料;
A1)我们看到,step2 和 step4 处理的代码是一样的,所以将step2 和 step4 抽取到基类并具体实现,而基类只给出 step1 和 step3  的 抽象定义,由子类去具体实现;
A2)具体荔枝:
package com.designpattern.chapter8;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");}}
package com.designpattern.chapter8;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");}}
package com.designpattern.chapter8;public class Tea extends CaffeineBeverage {public void brew() {System.out.println("Steeping the tea");}public void addCondiments() {System.out.println("Adding Lemon");}}
3)模板方法:定义了一个算法的steps,并允许子类的一个或多个steps提供实现;
Attention):这里要和我们的论文算法的实现联系起来,特别是对于机器学习的算法,其步骤都是一致的,可以结合模板方法模式来实现;(干货——将模板方法模式应用到机器学习的算法中)
4)钩子(hook): 钩子是一种被声明在抽象类中的方法,但只有空的实现或者默认的实现;(干货——引入钩子)
4.1)钩子的存在: 可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定;
4.2)使用钩子:我们在子类中覆盖它;
4.3)算法中某个操作是可选的,就用钩子;
package com.designpattern.chapter8;public abstract class CaffeineBeverageWithHook { final 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;}} }
【2】好莱坞原则
2.1)定义:别调用我们,我们会调用你;
2.2)在好莱坞原则下:我们允许底层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些底层组件。换句话说,高层组件对待底层组件的方式是“别调用我们,我们会调用你”;

2.3)好莱坞原则和模板方法的连接
对上图的分析(Analysis):饮料的客户代码只依赖CaffeineBeverage 抽象,而不依赖于具体的Tea 或 Coffee。这可以减少整个系统的依赖;

【3】用模板方法排序
3.1)还记得 Comparable 和 compareTo() 方法吗?这种比较大小的算法,采用的就是 模板方法模式;(干货——经典荔枝,模板方法模式应用于Arrays.sort 排序)
3.2)看个荔枝(Arrays.sort):
package com.designpattern.chapter8;public class Duck implements Comparable<Duck>{String name;int weight;public Duck(String name, int weight) {this.name = name;this.weight = weight;}@Overridepublic int compareTo(Duck o) {if(this.weight > o.weight)return -1;else if(this.weight == o.weight)return 0;elsereturn 1;}@Overridepublic String toString() {return "name: " + name + "weight: " + weight;}}
package com.designpattern.chapter8;import java.util.Arrays;public class MyTest {public static void main(String[] args) {Duck[] ducks = {new Duck("nihao9",9),new Duck("nihao10",10),new Duck("nihao8",8)};Arrays.sort(ducks);for (Duck duck : ducks) {System.out.println(duck);}}}
对Arrays.sort方法的分析(Analysis):
A1)sort的设计者希望这个方法能应用于所有的数组,所以他们把sort()变成是静态的方法,这样一来,任何数组都可以使用这个方法。但是没有关系,他使用起来和它被定义在超类中是一样的。现在,还有一个细节要告诉你:因为 sort()并不是真正定义在超类中,所以sort方法需要知道你已经实现了这个compareTo()方法就可以了,否则就无法进行排序。
A2)方法调用轨迹:MyTest.main() -> Arrays.sort() -> ComparableTimSort.sort() -> ComparableTimSort.binarySort() -> Comparable.compareTo()

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

0 0
原创粉丝点击