框架创建中常见设计模式-模板方法模式
Posted yangxiaojie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了框架创建中常见设计模式-模板方法模式相关的知识,希望对你有一定的参考价值。
模板方法模式
定义:在一个方法中定义一个算法的骨架,将一些处理的步骤延迟到子类去做处理,可以使在子类不改变算法结构的情况下, 重新定义算法的步骤。
设计院原则
好莱坞原则:别调用我们,我们会调用你。
先来看下简单的代码实现:
定义一个父类:果汁流程制作
1 package com.templateModePattern.parentClass; 2 3 /** 4 * @program: test 5 * @description: 果汁的制造简单流程:--》清洗水果 --》放入修饰材料--》放入榨汁机中 6 * 因为放入修饰材料的流程,各个果汁不一样,所以放入子类去实现 7 * @author: Mr.Yang 8 * @create: 2018-12-22 13:19 9 **/ 10 public abstract class FruitJuiceParent { 11 12 /** 13 * 果汁的制造流程(当作固定流程,不会变),这个方法不希望子类去覆盖, 14 *子类只需要实现putMaterial()方法就行,声明为final,骨架方法 15 */ 16 public final void makeFruitJuice(){ 17 cleanIts(); 18 putMaterial(); 19 putMachine(); 20 } 21 22 protected abstract void putMaterial(); 23 24 /** 25 * 清洗水果 26 */ 27 protected void cleanIts(){ 28 System.out.println("clean fruit"); 29 } 30 31 /** 32 * 放入榨汁机中 33 */ 34 protected void putMachine(){ 35 System.out.println("put machine"); 36 } 37 }
子类苹果汁,实现父类未实现的方法
1 package com.templateModePattern.subClass; 2 3 import com.templateModePattern.parentClass.FruitJuiceParent; 4 5 /** 6 * @program: test 7 * @description: 苹果汁 8 * @author: Mr.Yang 9 * @create: 2018-12-22 13:26 10 **/ 11 public class AppleFruitJuice extends FruitJuiceParent { 12 13 /** 14 * 在苹果汁放入蜂蜜,味道更好 15 */ 16 public void putMaterial() { 17 System.out.println("Put in honey"); 18 } 19 20 }
子类西瓜汁,实现父类未实现的方法
1 package com.templateModePattern.subClass; 2 3 import com.templateModePattern.parentClass.FruitJuiceParent; 4 5 /** 6 * @program: test 7 * @description: 西瓜汁 8 * @author: Mr.Yang 9 * @create: 2018-12-22 13:29 10 **/ 11 public class WatermelonFruitJuice extends FruitJuiceParent { 12 13 /** 14 * 放入牛奶,味道更好 15 */ 16 public void putMaterial() { 17 System.out.println("put in milk"); 18 } 19 }
挂钩
钩子是一种被声明在抽象类中的方法,但只有空的或者默认实现,钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,由子类自行决定。
在方法中加入挂钩代码实现
父类加入判断,如果true,去执行,让子类去具体实现该方法,做处理
1 package com.templateModePattern.parentClass; 2 3 /** 4 * @program: test 5 * @description: 果汁的制造简单流程:--》清洗水果 --》放入修饰材料--》放入榨汁机中 6 * 因为放入修饰材料的流程,各个果汁不一样,所以放入子类去实现 7 * @author: Mr.Yang 8 * @create: 2018-12-22 13:19 9 **/ 10 public abstract class FruitJuiceParent { 11 12 /** 13 * 果汁的制造流程(当作固定流程,不会变),这个方法不希望子类去覆盖, 14 * 子类只需要实现putMaterial()方法就行,声明为final 15 */ 16 public final void makeFruitJuice(){ 17 cleanIts(); 18 if(isPutMaterIal()){ 19 putMaterial(); 20 } 21 putMachine(); 22 } 23 24 protected abstract void putMaterial(); 25 26 /** 27 * 清洗水果 28 */ 29 protected void cleanIts(){ 30 System.out.println("clean fruit"); 31 } 32 33 /** 34 * 放入榨汁机中 35 */ 36 protected void putMachine(){ 37 System.out.println("put machine"); 38 } 39 40 /** 41 * 父类增加判断 42 * @return 43 */ 44 protected boolean isPutMaterIal(){ 45 return true; 46 } 47 }
苹果汁子类让用户去做选择
1 package com.templateModePattern.subClass; 2 3 import com.templateModePattern.parentClass.FruitJuiceParent; 4 import org.apache.commons.lang3.StringUtils; 5 6 import java.io.BufferedReader; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 10 /** 11 * @program: test 12 * @description: 苹果汁 13 * @author: Mr.Yang 14 * @create: 2018-12-22 13:26 15 **/ 16 public class AppleFruitJuice extends FruitJuiceParent { 17 18 /** 19 * 在苹果汁放入蜂蜜,味道更好 20 */ 21 public void putMaterial() { 22 System.out.println("Put in honey"); 23 } 24 25 /** 26 * 在子类覆盖它,让用户去选择 27 * @return 28 */ 29 @Override 30 protected boolean isPutMaterIal() { 31 String userInput = getUserInput(); 32 if(userInput.toLowerCase().startsWith("y")){ 33 return true; 34 }else{ 35 return false; 36 } 37 } 38 39 /** 40 * 得到用户输入的内容 41 * @return 42 */ 43 private String getUserInput(){ 44 String readString=null; 45 System.out.println("Do you want honey(y/n)?"); 46 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 47 try { 48 readString = br.readLine(); 49 } catch (IOException e) { 50 System.out.println("---异常---"+e); 51 } 52 if(StringUtils.isEmpty(readString)){ 53 return "N"; 54 }else{ 55 return readString; 56 } 57 } 58 }
西瓜汁子类让用户去做选择
1 package com.templateModePattern.subClass; 2 3 import com.templateModePattern.parentClass.FruitJuiceParent; 4 import org.apache.commons.lang3.StringUtils; 5 6 import java.io.BufferedReader; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 10 /** 11 * @program: test 12 * @description: 西瓜汁 13 * @author: Mr.Yang 14 * @create: 2018-12-22 13:29 15 **/ 16 public class WatermelonFruitJuice extends FruitJuiceParent { 17 18 /** 19 * 放入牛奶,味道更好 20 */ 21 public void putMaterial() { 22 System.out.println("put in milk"); 23 } 24 25 26 /** 27 * 在子类覆盖它,让用户去选择 28 * @return 29 */ 30 @Override 31 protected boolean isPutMaterIal() { 32 String userInput = getUserInput(); 33 if(userInput.toLowerCase().startsWith("y")){ 34 return true; 35 }else{ 36 return false; 37 } 38 } 39 40 /** 41 * 得到用户输入的内容 42 * @return 43 */ 44 private String getUserInput(){ 45 String readString=null; 46 System.out.println("Do you want milk(y/n)?"); 47 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 48 try { 49 readString = br.readLine(); 50 } catch (IOException e) { 51 System.out.println("---异常---"+e); 52 } 53 if(StringUtils.isEmpty(readString)){ 54 return "N"; 55 }else{ 56 return readString; 57 } 58 } 59 }
制造无添加草莓汁
1 package com.templateModePattern.subClass; 2 3 import com.templateModePattern.parentClass.FruitJuiceParent; 4 5 /** 6 * @program: test 7 * @description: 草莓汁,无添加 8 * @author: Mr.Yang 9 * @create: 2018-12-22 13:46 10 **/ 11 public class StrawberryFruitJuice extends FruitJuiceParent { 12 13 protected void putMaterial() { 14 15 } 16 17 @Override 18 protected boolean isPutMaterIal() { 19 return false; 20 } 21 }
测试结果:
1 ____________苹果汁制作开始____________ 2 clean fruit 3 Do you want honey(y/n)? 4 y 5 Put in honey 6 put machine 7 ____________苹果汁制作结束____________ 8 9 10 ____________草莓汁制作开始____________ 11 clean fruit 12 put machine 13 ____________草莓汁制作结束____________ 14 15 16 ____________西瓜汁制作____________ 17 clean fruit 18 Do you want milk(y/n)? 19 n 20 put machine 21 ____________西瓜汁结束____________
好莱坞原则与依赖倒置原则的区别
依赖倒置提倡避免使用具体类,多使用抽象。
好莱坞原则是用在创建框架或组件上的一种技巧,让底层组件能够被挂钩计算中,又不会让高层组件依赖低层组件。
重点内容与比较
1.模板方法定义了算法的步骤,将步骤的实例延迟到子类
2.提供了一种代码复用的技巧
3.钩子的了解与使用
4.好莱坞原则提倡将决策权放到高层(父类)
5.策略模式和模板方法模式都封装算法,一个用组合,一个用继承
以上是关于框架创建中常见设计模式-模板方法模式的主要内容,如果未能解决你的问题,请参考以下文章
设计模式 - 学习笔记 - TemplateMethod 模板方法