框架创建中常见设计模式-模板方法模式
时间:2022-06-24
本文章向大家介绍框架创建中常见设计模式-模板方法模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
模板方法模式 定义:在一个方法中定义一个算法的骨架,将一些处理的步骤延迟到子类去做处理,可以使在子类不改变算法结构的情况下, 重新定义算法的步骤。
设计_原则
好莱坞原则:别调用我们,我们会调用你。
先来看下简单的代码实现:
定义一个父类:果汁流程制作
1package com.templateModePattern.parentClass;
2
3/**
4 * @program: test
5 * @description: 果汁的制造简单流程:--》清洗水果 --》放入修饰材料--》放入榨汁机中
6 * 因为放入修饰材料的流程,各个果汁不一样,所以放入子类去实现
7 * @author: Mr.Yang
8 * @create: 2018-12-22 13:19
9 **/
10public 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}
子类苹果汁,实现父类未实现的方法
1package com.templateModePattern.subClass;
2
3import com.templateModePattern.parentClass.FruitJuiceParent;
4
5/**
6 * @program: test
7 * @description: 苹果汁
8 * @author: Mr.Yang
9 * @create: 2018-12-22 13:26
10 **/
11public class AppleFruitJuice extends FruitJuiceParent {
12
13 /**
14 * 在苹果汁放入蜂蜜,味道更好
15 */
16 public void putMaterial() {
17 System.out.println("Put in honey");
18 }
19
20}
子类西瓜汁,实现父类未实现的方法
1package com.templateModePattern.subClass;
2
3import com.templateModePattern.parentClass.FruitJuiceParent;
4
5/**
6 * @program: test
7 * @description: 西瓜汁
8 * @author: Mr.Yang
9 * @create: 2018-12-22 13:29
10 **/
11public class WatermelonFruitJuice extends FruitJuiceParent {
12
13 /**
14 * 放入牛奶,味道更好
15 */
16 public void putMaterial() {
17 System.out.println("put in milk");
18 }
19}
挂钩
钩子是一种被声明在抽象类中的方法,但只有空的或者默认实现,钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,由子类自行决定。
在方法中加入挂钩代码实现
父类加入判断,如果true,去执行,让子类去具体实现该方法,做处理
1package com.templateModePattern.parentClass;
2
3/**
4 * @program: test
5 * @description: 果汁的制造简单流程:--》清洗水果 --》放入修饰材料--》放入榨汁机中
6 * 因为放入修饰材料的流程,各个果汁不一样,所以放入子类去实现
7 * @author: Mr.Yang
8 * @create: 2018-12-22 13:19
9 **/
10public 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}
苹果汁子类让用户去做选择
1package com.templateModePattern.subClass;
2
3import com.templateModePattern.parentClass.FruitJuiceParent;
4import org.apache.commons.lang3.StringUtils;
5
6import java.io.BufferedReader;
7import java.io.IOException;
8import java.io.InputStreamReader;
9
10/**
11 * @program: test
12 * @description: 苹果汁
13 * @author: Mr.Yang
14 * @create: 2018-12-22 13:26
15 **/
16public 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}
西瓜汁子类让用户去做选择
1package com.templateModePattern.subClass;
2
3import com.templateModePattern.parentClass.FruitJuiceParent;
4import org.apache.commons.lang3.StringUtils;
5
6import java.io.BufferedReader;
7import java.io.IOException;
8import java.io.InputStreamReader;
9
10/**
11 * @program: test
12 * @description: 西瓜汁
13 * @author: Mr.Yang
14 * @create: 2018-12-22 13:29
15 **/
16public 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}
制造无添加草莓汁
1package com.templateModePattern.subClass;
2
3import com.templateModePattern.parentClass.FruitJuiceParent;
4
5/**
6 * @program: test
7 * @description: 草莓汁,无添加
8 * @author: Mr.Yang
9 * @create: 2018-12-22 13:46
10 **/
11public class StrawberryFruitJuice extends FruitJuiceParent {
12
13 protected void putMaterial() {
14
15 }
16
17 @Override
18 protected boolean isPutMaterIal() {
19 return false;
20 }
21}
测试结果:
1____________苹果汁制作开始____________
2clean fruit
3Do you want honey(y/n)?
4y
5Put in honey
6put machine
7____________苹果汁制作结束____________
8
9
10____________草莓汁制作开始____________
11clean fruit
12put machine
13____________草莓汁制作结束____________
14
15
16____________西瓜汁制作____________
17clean fruit
18Do you want milk(y/n)?
19n
20put machine
21____________西瓜汁结束____________
好莱坞原则与依赖倒置原则的区别
依赖倒置提倡避免使用具体类,多使用抽象。 好莱坞原则是用在创建框架或组件上的一种技巧,让底层组件能够被挂钩计算中,又不会让高层组件依赖低层组件。
重点内容与比较
1.模板方法定义了算法的步骤,将步骤的实例延迟到子类 2.提供了一种代码复用的技巧 3.钩子的了解与使用 4.好莱坞原则提倡将决策权放到高层(父类) 5.策略模式和模板方法模式都封装算法,一个用组合,一个用继承
- android事件总线
- Nginx架构初探(值得细品的长篇好文)
- android fragement报nullexcption错误
- 小白爬虫之爬虫快跑,多进程和多线程
- popupwindow和listview
- Debian 和Ubuntu Mono 3.0 部署包
- Apache Storm内部原理分析
- 使用lrucache和diskLrucache实现照片墙
- android 减少图片出现oom错误
- android分包方案
- 系统负载能力浅析
- 微软正式发布了Microsoft.Bcl.Async
- parcel和parcelable
- Windows Phone 7 WebBrowser 中文乱码问题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于 SkyWalking 实现服务链路追踪
- Python 技巧篇-字符串灵活处理:字符串过滤、字符串拼接,字符串切片,特殊、超长字符串的处理实例演示
- Python 技巧篇-开头注释怎么写最好,开头注释需要包含什么,开头注释的重要性
- 在CentOS8下安装Python3和ansible
- 开发一个属于自己的Spring Boot Starter
- 如何让Tomcat使用APR连接器
- VueJS中使用前端虚拟接口Mock.js
- CentOS7下源码安装MySQL 8.x
- 最新!中国天气网api接口调用,key获取方式,数据请求秘钥获取,城市id获取方法
- Jmeter接口压测快速入门
- 超简单!Qt Designer插入图片,styleSheet加入图片,Qt加入背景图片
- 关于领域模型转换的那些事儿
- Windows图标显示异常解决方法。桌面图标异常,开始菜单图标异常,任务栏图标异常。图标缓存位置。
- Python基本语法与数字类型
- Qt Designer设置背景图片、颜色不影响其它组件小技巧,控件层级设置,组件的继承,styleSheet设置样式。