设计模式学习笔记--模板方法模式
1.设计原则
好莱坞原则:底层组件可以挂钩到我们自己的系统上,由高层组件决定合适调用以及如何使用低层组件,但是低层组件绝对不可以去直接调用高层组件
2.学习笔记
· 模板方法模式:模板方法定义了一个算法的步骤,抽离出相同的操作,并允许子类为一个或多个步骤提供具体实现
· 钩子(hook):被声明在抽象类中的方法,只有空的活着默认的实现,子类可以根据实际情况决定是否要进行覆盖钩子(hook)方法
· 钩子(hook)使用的真正目的:
1. 可以让子类实现算法中可选部分
2. 可以让子类能够有机会对模板中某些即将发生(或刚刚发生)的步骤作出反应
· 工厂方法是模板方法的一个特殊版本
3.代码实践——以烧菜为例
· 1. 实现一个抽象类,实现共有的方法,并将子类需要实现的方法分离为抽象方法
package headFirst.templateDesignPattern; /** * @author kaithy.xu * @date 2019/4/14 14:13 */ public abstract class FoodCook { //模版方法,定义为final,防止子类覆盖 final void prepareDinner(){ prepareFood(); powerOn(); cookMethod(); addCondiments(); pourInPlate(); if (hook()){ annouceDinnerIsReady(); } } //抽象方法,准备食物 abstract void prepareFood(); //抽象方法,选择烹饪方式 abstract void cookMethod(); //抽象方法,选择添加的配料 abstract void addCondiments(); //公共方法在抽象类中实现,子类可以自己选择是否覆盖 void powerOn(){ System.out.println("the induction cooker is electrified"); } //公共方法 void pourInPlate(){ System.out.println("the food is cooked and is poured in plate"); } void annouceDinnerIsReady(){ System.out.println("tell everyone dinner is ready"); } //默认hook方法,当子类不覆盖此方法时,模板中使用此方法 boolean hook(){ return false; } }
·2. 子类继承此抽象类,并实现抽象方法,实现子类自己独有的方法
package headFirst.templateDesignPattern; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @author kaithy.xu * @date 2019/4/14 14:24 */ public class CookFish extends FoodCook { @Override void prepareFood() { System.out.println("scale and gut fish"); } @Override void cookMethod() { System.out.println("braise fish in brown sauce"); } @Override void addCondiments() { System.out.println("add shallot, ginger and garlic"); } //子类实现hook方法,通过用户输入以决定模板方法的走向 @Override boolean hook() { String answer = null; BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (true){ System.out.println("is dinner ready ? (y/n)"); try { answer = in.readLine(); }catch (IOException e){ System.out.println("IO error trying to read your answer"); } if(answer == null || answer.equalsIgnoreCase("n")){ return false; }else if(answer.equalsIgnoreCase("y")){ return true; }else { System.out.println("wrong input,please input again \n"); } } } }
package headFirst.templateDesignPattern; /** * @author kaithy.xu * @date 2019/4/14 14:31 */ public class CookDrumstick extends FoodCook { @Override void prepareFood() { System.out.println("wash the drumsticks with boiled water, widen the opening with knife"); } @Override void cookMethod() { System.out.println("deep fry the drumsticks and pour the coca cola after the color of drumsticks turn into golden "); } @Override void addCondiments() { System.out.println("add rock candy , yellow rice wine and light soy sauce and dark soy sauce"); } }
·3. 用户调用
package headFirst.templateDesignPattern; /** * @author kaithy.xu * @date 2019/4/14 15:06 */ public class Client { public static void main(String[] args){ CookDrumstick drumstick = new CookDrumstick(); drumstick.prepareDinner(); CookFish fish = new CookFish(); fish.prepareDinner(); } }
4.类结构图
· 范例代码类结构图
·模板方法UML图:
抽象类中含有模板方法,模板方法在实现算法的过程中,使用了primitiveOperation1() 和 primitiveOperation2()这两个原语操作,模板本身和这两个操作的具体实现之间被解耦了,在子类中,需要要实现模板所必需的原语操作,这样当模板需要使用原语操作的时候,会到子类中去调用

浙公网安备 33010602011771号