1.概述
定义一个操作中的算法骨架,而将步骤实现延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重写定义算法的某些特定步骤。
我们可以简单的理解成,我们要进行一次越野赛,起点终点固定,中间我们可以自己选择不同的路线和方式从起点跑到终点。
2.模式中的角色
2.1抽象类:
实现了模板方法,定义了算法的骨架。(正如上例中的规定了起点和终点,中间的选择路线我们不去关心)。
2.2具体子类:
继承抽象类,实现抽象类中的抽象方法,已完成完整的算法。(自行选择了中间的路线和方法,并且完成越野赛,最终成功从起点跑到终点)。
3.模式的解读
3.1模板方法类图
4.模板方法的应用
4.1实例一:打印文章
比如我们想打印一篇文章,我们要打印标题,打印正文,打印结尾。
那么首先我们可以这样实现:
public class Print {
public void print() {
printHead();
printBoyd();
printBottom();
}
public void printHead() {
System.out.println("打印头");
}
public void printBoyd() {
System.out.println("打印中间");
}
public void printBottom() {
System.out.println("打印尾");
}
}
但是这样存在一个问题,我们这样做就把打印操作给固定了。固定后如果我们打印需求有新的变化,比如改下标题头,我们就得去修改代码这样是不符合开放拓展,关闭修改的设计原则。我们怎样才能解决呢,使用模板方法模式可以帮我们完美解决。
/*
* 定义了一个打印的模板类,我们先创建出骨架,具体实现先不去关心
*/
public abstract class PrintTemplet {
public void print() {
printHead();
printBody();
printBottom();
}
public abstract void printHead();
public abstract void printBody();
public abstract void printBottom();
}
<pre name="code" class="java">/*
* 定义了一个打印的实现类1,以第一种方式打印
*/
public class PrintDemo1 extends PrintTemplet {
@Override
public void printHead() {
System.out.println("采用第一种方案打印头");
}
@Override
public void printBody() {
System.out.println("采用第一种方案打印中间");
}
@Override
public void printBottom() {
System.out.println("采用第一种方案打印尾");
}
}
/*
* 定义了一个打印的实现类2,以第二种方式打印
*/
public class PrintDemo2 extends PrintTemplet {
@Override
public void printHead() {
System.out.println("采用第二种方案打印头");
}
@Override
public void printBody() {
System.out.println("采用第二种方案打印中间");
}
@Override
public void printBottom() {
System.out.println("采用第二种方案打印尾");
}
}
<pre name="code" class="java">/*
* 测试类
*/
public class PrintTest {
public static void main(String[] args) {
// Print p = new Print();
// p.print();
PrintTemplet pt = new PrintDemo1();
pt.print();
System.out.println("------------");
pt = new PrintDemo2();
pt.print();
}
}
这样子类灵活的以自己方式实现了打印的文章。
4.2实例二:计算代码执行的时间
计算一段代码的执行时间的逻辑其实很简单,在测试代码执行前记录一下当前时间,在测试代码执行完在记录下当前时间,终止时间减去开始时间即可。
下面我们直接用模板方法去实现这个功能。以测试拷贝一张图片时间为例。
//测试抽象类
public abstract class ProgramTimeTemplet {
// 具体的操作
public long getTime() {
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
return (end - start);
}
// 抽象的代码方法
public abstract void code();
}
//测试拷贝图片的实现类
public class ProgramTimeTempletIODemo extends ProgramTimeTemplet {
@Override
public void code() {
try {
FileInputStream fis = new FileInputStream("d:\\干程序员前后.bmp");//得到输入流
FileOutputStream fos = new FileOutputStream("1.bmp");//得到输出流
int by = 0;<span style="white-space:pre"> </span> //开始拷贝
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//测试代码
public class ProgramTimeTest {
public static void main(String[] args) throws IOException {
ProgramTimeTemplet ptt = new ProgramTimeTempletIODemo();
System.out.println(ptt.getTime() + "毫秒");
}
}
这样我们可以很轻易的拿到拷贝图片所用的时间。那么如果我们想测试一个for循环的执行时间呢?
用了模板方法模式,我们可以轻松完成,它具有良好的拓展性,灵活性。我们只需写一个实现类,继承抽象类,实现里面的code()方法,在code()方法中执行要测试的for循环即可。下面是实现代码:
//测试for循环的实现类
public class ProgramTimeTempletForDemo extends ProgramTimeTemplet {
@Override
public void code() {
for (int x = 0; x < 1000000; x++) {
System.out.println(x);
}
}
}
/测试类
public class ProgramTimeTest {
public static void main(String[] args) throws IOException {
//ProgramTimeDemo ptd = new ProgramTimeDemo();
// ptd.showTime();
ProgramTimeTemplet ptt = new ProgramTimeTempletIODemo();
// System.out.println(ptt.getTime() + "毫秒");
ptt = new ProgramTimeTempletForDemo();
System.out.println(ptt.getTime() + "毫秒");
}
}
好了这次模板方法模式就为大家介绍到这里,大家,晚安。