设计模式学习笔记(十八:模板方法模式)
1.1概述
定义了一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。这就是模板方法的定义。
类中的方法用以表明该类的实例所具有的行为,一个类可以有许多方法,而且类中的实例方法也可以调用该类中的其他若干个方法。在编写类的时候,可能需要将类的许多方法集成到一个实例方法中,即用一个实例方法封装若干个方法的调用,以表现一个算法的骨架,也就是说,调用该实例方法相当于按着一定顺序执行若干个方法。
例如,各类客运车站在安排乘客上车时都进行安全检查、验证车票、选择车体类型三个步骤(具体如下图一所示)。因此在一个抽象类Station中包含安全检查方法(safetyExamine)、验证车票方法(validateTicket)、选择车体类型方法(choiceCarriageType)表示乘车步骤的抽象方法,而且该抽象类中还包含有ridingStep()方法,该方法顺序调用安全检查方法、验证车票方法、选择车体类型方法,也就是说抽象类Station使用ridingStep()方法封装了乘车步骤。ridingStep()方法所调用的safetyExamine()、validateTicket()、choiceCarriageType()方法都是抽象方法,因此Station的子类:RailwayStation(火车站)在实现safetyExamine()、validateTicket()、choiceCarriageType()方法时,分别给出了自己的安全检查方式、检票车票方式和所选车体类型。当Station类声明的变量存放它的子类RailwayStation实例的引用后,该变量就可以调用ridingStep()方法展示乘客的乘车步骤。具体类关系图如下图一所示:
图一:乘车步骤
模板方法是关于怎样将若干个方法集成到一个方法中,以便形成一个解决问题的算法骨架。模板方法模式的关键是在一个抽象类中定义一个算法的骨架,即将若干个方法集成到一个方法中,并称该方法为一个模板方法,或简称为模板。模板方法所调用的其他方法通常称为抽象的方法,这些抽象方法相当于算法骨架中的各个步骤,这些步骤可以由子类去完成。
1.2模式的结构
模板方法模式包括以下两种角色:
(1)抽象模板(Abstract Template):抽象模板是一个抽象类。抽象模板定义了若干个方法以表示算法的各个步骤,这些方法中有抽象方法也有非抽象方法,其中的抽象方法称为原语操作(Primitive Operation)。重要的一点是,抽象模板中还定义了一个称之为模板方法的方法,该方法不仅包含有抽象模板中表示算法步骤的方法调用,而且也可以包含有定义在抽象模板中的其他对象的方法调用,即模板方法定义了算法的骨架。
(2)具体模板(Concrete Template):具体模板是抽象模板的子类,实现抽象模板中的原语操作。
模板方法模式结构的类图如下图二所示:
图二:模板方法模式的类图
1.3模板方法模式的优点
(1)可以通过在抽象模板定义模板方法给出成熟的算法步骤,同时又不限制步骤的细节,具体模板实现细节不会改变整个算法的框架。
(2)在抽象模板模式中,可以通过钩子方法对某些步骤进行挂钩,具体模板通过钩子可以选择算法骨架中的某些步骤。
1.4适合使用模板方法模式的情景
(1)设计者需要给出一个算法的固定步骤,并将某些步骤的具体实现留给子类来实现。
(2)需要对代码进行重构,将各个子类公共行为提取出来集中到一个共同的父类中以避免代码重复。
1.5模板方法模式的使用
以下通过一个简单的问题来描述怎样使用模板方法模式,这个简单的问题是:显示某个目录下全部文件的名字,比如可以按照文件的大小顺序、按最后修改的时间顺序或按文件名字的字典顺序来显示某个目录下全部文件的名字。
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:
(1)抽象模板(Abstract Template)
本问题中,抽象模板(Abstract Template)角色是AbstractTemplate类。抽象模板中的模板方法是showFileName();抽象模板中表示具体步骤的方法是sort()和printFiles()方法,二者都是原语操作。具体代码如下:
package com.liuzhen.eighteen_template;import java.io.*;public abstract class AbstractTemplate {File[] allFiles;File dir;AbstractTemplate(File dir){this.dir = dir;}public final void showFileName(){allFiles = dir.listFiles();sort();printFiles();}public abstract void sort();public abstract void printFiles(); }
(2)具体模板(Concrete Template)
对于本问题,具体模板是ConcreteTemplate1和ConcreteTemplate2类。ConcreteTemplate1中的sort()方法把目录下的文件名字按其所引用文件被最后修改的时间顺序排列;ConcreteTemplate2中的sort()方法把目录下的文件名字按照其所引用文件的大小顺序排列。其具体代码如下:
ConcreteTemplate1.java
package com.liuzhen.eighteen_template;import java.io.File; import java.text.SimpleDateFormat; import java.util.Date;public class ConcreteTemplate1 extends AbstractTemplate {ConcreteTemplate1(File dir) {super(dir);}@Overridepublic void sort() {for(int i = 0;i < allFiles.length;i++){for(int j = i+1;j < allFiles.length;j++){if(allFiles[j].lastModified() < allFiles[i].lastModified()){File file = allFiles[j];allFiles[j] = allFiles[i];allFiles[i] = file;}}}}@Overridepublic void printFiles() {for(int i = 0;i < allFiles.length;i++){long time = allFiles[i].lastModified();Date date = new Date(time);SimpleDateFormat matter = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");String str = matter.format(date);String name = allFiles[i].getName();int k = i+1;System.out.println(k+" "+name+"("+str+")");}}}
ConcreteTemplate2.java
package com.liuzhen.eighteen_template;import java.io.File;public class ConcreteTemplate2 extends AbstractTemplate {ConcreteTemplate2(File dir) {super(dir);}@Overridepublic void sort() {for(int i = 0;i < allFiles.length;i++){for(int j = i+1;j < allFiles.length;j++){if(allFiles[j].length() < allFiles[i].length()){File file = allFiles[i];allFiles[i] = allFiles[j];allFiles[j] = file;}}}}@Overridepublic void printFiles() {for(int i = 0;i < allFiles.length;i++){long fileSize = allFiles[i].length();String name = allFiles[i].getName();int k = i+1;System.out.println(k+" "+name+"("+fileSize+" 字节)");}}}
(3)具体使用
通过EighteenApplication类来具体实现上述相关类和接口,来实现状态模式的运用,其代码如下:
package com.liuzhen.eighteen_template;import java.io.File;public class EighteenApplication {public static void main(String[] args){File dir = new File("E:/KuGou");AbstractTemplate template = new ConcreteTemplate1(dir);System.out.println(dir.getPath()+"目录下的文件:");template.showFileName();System.out.println();template = new ConcreteTemplate2(dir);System.out.println(dir.getPath()+"目录下的文件:");template.showFileName();} }
运行结果:
E:\KuGou目录下的文件: 1 罗凯楠 - 咱们屯里的人.mp3(2015-29-11 11:29:37) 2 唐家大小姐 - 超越时空的思念(中文演唱).mp3(2016-50-17 10:50:35) 3 陈悦 - 乱红 - 钢琴版伴奏.mp3(2016-12-16 05:12:42) 4 Cache(2017-55-23 05:55:03) 5 Temp(2017-09-23 07:09:17) 6 Lyric(2017-09-23 07:09:18)E:\KuGou目录下的文件: 1 Cache(4096 字节) 2 Lyric(4096 字节) 3 Temp(81920 字节) 4 唐家大小姐 - 超越时空的思念(中文演唱).mp3(2887753 字节) 5 陈悦 - 乱红 - 钢琴版伴奏.mp3(4965609 字节) 6 罗凯楠 - 咱们屯里的人.mp3(5480489 字节)
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5
转载于:https://www.cnblogs.com/liuzhen1995/p/6036551.html
设计模式学习笔记(十八:模板方法模式)相关推荐
- 设计模式学习笔记十五——Command模式
动机:将一组行为抽象为对象,实现行为请求者和行为实现者之间的解耦,并且支持对行为进行记录.撤销.重做.事务等处理. 场景:考虑一系列文档操作:打开.复制.剪切.粘帖. 结构 代码实现 /**//* ...
- java 设计模式学习笔记十 bridge桥模式
bridge桥模式 将抽象和行为划分开来,各自独立但能动态结合 抽象的接口 /** * 咖啡抽象类 * * @time 下午09:14:27 * @author retacn yue * ...
- windows内核开发学习笔记十八:IRP 处理的标准模式
windows内核开发学习笔记十八:IRP 处理的标准模式 在 Windows 内核中的请求基本上是通过 I/O Request Packet 完成的. I/O manager ---> Dis ...
- 设计模式学习笔记——享元(Flyweight)模式
设计模式学习笔记--享元(Flyweight)模式 @(设计模式)[设计模式, 享元模式, flyweight] 设计模式学习笔记享元Flyweight模式 基本介绍 享元案例 类图 实现代码 Big ...
- 设计模式学习笔记——中介者(Mediator)模式
设计模式学习笔记--中介者(Mediator)模式 @(设计模式)[设计模式, 中介者模式, Mediator] 设计模式学习笔记中介者Mediator模式 基本介绍 中介者案例 类图 实现代码 Me ...
- 设计模式学习笔记——单例(Singleton)模式
设计模式学习笔记--单例(Singleton)模式 @(设计模式)[设计模式, 单例模式, Singleton, 懒汉式, 饿汉式] 设计模式学习笔记单例Singleton模式 基本介绍 单例案例 类 ...
- python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置...
python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置 Download JetBrains Python IDE :: PyCharm http://ww ...
- Polyworks脚本开发学习笔记(十八)-用SDK开发Polyworks插件
Polyworks脚本开发学习笔记(十八)-用SDK开发Polyworks插件 插件是由PolyWorks加载的动态链接库(DLL文件),然后查询Polyworks模块,以确定它们具有哪些功能,提供给 ...
- 设计模式学习笔记--Mediator 中介者模式
我们知道面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成.当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点).而当对象的数量增加时,这种直接交互会导致对象之间复杂的.混乱的引 ...
- 设计模式学习笔记--Flyweight享元模式
Flyweight模式也叫享元模式,是由GoF提出的23种设计模式中的一种.Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用,所以叫享元. 此模式解决的是由于大量 ...
最新文章
- 程序的跟踪debug
- 行人检测资源综述文献
- 无记忆多项式数字预失真技术
- JAVA基础:Hibernate外键关联与HQL语法
- linux系统在pe下查看ip地址,pe下查看原系统ip的方法_网站服务器运行维护
- java向注册表单传递数据php_PHP提交from表单的方法
- labview实例_手把手以实例教你学LabVIEW编程,事件结构框架
- java java se_Java 8 SE可选,严格的方法
- 【开源】我的分页控件正式命名为QuickPager ASP.NET2.0分页控件
- perl调用其他的perl_如何使Perl更优雅
- 类似mysqlhotcopy备份mysql myisam脚本
- OpenShift 4 Hands-on Lab (13) 使用持久化存储
- Eclipse批量替换
- 语音识别概念午后大跌 语音识别概念股一览表
- Atitit 并发技术的选项 attilax总结 艾龙 著 1. 三大并发模型	1 2. 从可读性考虑 优先使用 并行工作者 多线程模式,不要使用异步流水线模式	2 2.1. 多线程模式方便全局
- dcs world f15c教学_DCS小百科,工控人必须知道的一些小知识
- IBM的量子云计算准备开始商用 我国此前已实现量子加密产品商用
- android 自定义消息,TUIKit Android自定义消息
- 情感分类模型介绍CNN、RNN、LSTM、栈式双向LSTM
- Canon背后的故事