《Head First 设计模式》学习笔记——模板方法模式

来源:互联网 发布:淘宝换类目影响权重不 编辑:程序博客网 时间:2024/05/17 01:42
模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

设计模式
模板方法模式:在一个方法中定义一个算法的框架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结果的情况下,重新定义算法中的某些步骤。
模板就是一个方法,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这样可以确保算法的结构保持不变,同时由子类提供部分实现。

钩子是一种被声明在抽象类中的方法,但只有空或默认的实现,钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,有子类自行决定。
使用钩子的真正目的:
钩子可以让子类实现算法中可选的部分,或者在钩子对于子类的实现并不重要的时候,子类可以对此钩子置之不理。钩子的另一个用法,是让子类能够有机会对模板方法中某些即将发生的(或刚刚发生的)步骤做出反应。

设计原则
好莱坞原则:别调用我们,我们会调用你。
在好莱坞原则下,我们允许低层组件将自己挂钩到系统之上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对低层组件的方式是“别调用我们,我们会调用你”。

要点
“模板方法”定义了算法的步骤,把这些步骤的实现延迟到子类中。
模板方法模式为我们提供了一种代码复用的重要技巧。
模板方法的抽象类可以定义具体方法、抽象方法、钩子。
为了防止子类改变模板方法中的算法,我们可以将模板方法声明为final。
策略模式和模板方法模式都是封装算法,前者是使用组合,后者是使用继承。
工厂方法是模板方式的一种特殊版本。

典型的摸板方法应用
1. HttpServlet技术
2. Swing的窗口程序
3. Applet

模板方法模式:
//声明为抽象类,子类必须实现其操作public abstract class CaffeineBeverage{//声明为final,不希望子类覆盖这个方法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");}}//extends继承public class Tea extends CaffeineBeverage {//需要定义抽象方法public void brew() {System.out.println("Steeping the tea");}public void addCondiments() {System.out.println("Adding Lemon");}}

使用钩子:
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;}}


0 0
原创粉丝点击