转载自:https://www.cnblogs.com/zplogo/p/6428593.html
用抽象基类定义算法框架 RefreshBeverage
package com.pattern.template; /** * 抽象基类,为其他子类提供一个算法框架 提神饮料 * * */ public abstract class RefreshBeverage { /* * 制备饮料的模板方法 封装了所有子类所遵循的算法框架 */ public final void prepareBeverageTemplate() { // 步骤一 将水煮沸 boilWater(); // 步骤二 泡制饮料 brew(); // 步骤三 将饮料倒入杯中 pourInCup(); if (isCustomerWantsCondiments()) { // 步骤四 加入调味料 addCondiments(); } } /* * Hook 钩子函数,提供一个空的或者默认的实现 子类重写该方法,可以自行决定是否挂钩以及如何挂钩 */ protected boolean isCustomerWantsCondiments() { return true; } // 因为将水煮沸和把饮料倒入杯中对所有子类是共同的行为,所以没必要向子类过多开放,所以方法定义为private,这样我们在进行子类编码时可以减少复杂度。 // 这样不需要关注细枝末节,我们只需要关注我们特定业务的实现,这就是模板方法模式的好处。可以封装变与不变,将不变的固化在高层,隐藏其细节。 private void boilWater() { System.out.println("将水煮沸"); } private void pourInCup() { System.out.println("将饮料倒入杯中"); } /* * 泡制饮料brew()和加入调料品addCondiments()这两个方法我们不知道它们在算法框架中的具体实现,因此定义为抽象方法, * 我们用protected进行修饰, 在子类中可见便于进行重写。 */ protected abstract void brew(); protected abstract void addCondiments(); }
具体子类延迟实现步骤 Coffee
package com.pattern.template; /** * 提供制备咖啡的具体实现子类。 具体子类实现延迟步骤,满足特定的业务需求。 * * */ public class Coffee extends RefreshBeverage { protected void brew() { System.out.println("步骤二 用沸水冲泡咖啡"); } protected void addCondiments() { System.out.println("步骤四 加入糖和牛奶"); } }
钩子使子类更灵活 Tea
package com.pattern.template; public class Tea extends RefreshBeverage { protected void brew() { System.out.println("步骤二 用80度热水浸泡茶叶5分钟"); } protected void addCondiments() { System.out.println("步骤四 加入柠檬"); } protected boolean isCustomerWantsCondiments() { return false; } }
测试类 RefreshBeverageTest
package com.pattern.template; public class RefreshBeverageTest { public static void main(String[] args) { System.out.println("制备咖啡中······"); RefreshBeverage b1 = new Coffee(); b1.prepareBeverageTemplate(); System.out.println("咖啡好了········"); // 制备茶的测试代码 System.out.println(" *********************************"); System.out.println("制备茶水中······"); RefreshBeverage b2 = new Tea(); b2.prepareBeverageTemplate(); System.out.println("茶水好了······"); } }