在开始本文之前,我们先来看下生活中的一些场景,比如造房子。有一个基本的骨架,每栋房子又可以有自己的特点,比如加个旗子,加一个塔楼等。
这样定义一个操作的骨架,然后将一些步骤延迟到子类中去实现的场景就是我们今天要讲的模板方法模式要做的事情。
意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
结构
模板方法的基本结构如下:
这里涉及到两个角色:
模板方法中的方法可以分为两大类:
模板方法(template method)和基本方法(Primitive method)
示例描述
模拟读取不同文件格式,然后输出读取内容的场景。每个处理包括验证文件、解析文件数据、展示数据内容的通用步骤。
package com.wangmengjun.tutorial.designpattern.template;
public abstract class AbstarctHandler {
/**模板方法**/
public final void process(String filepath) {
begin();
validate(filepath);
parseData(filepath);
display(filepath);
end();
}
/**抽象方法子类实现**/
public abstract void validate(String filepath);
public abstract void parseData(String filepath);
public abstract void display(String filepath);
/**钩子方法**/
public void hookMethod() {}
/**具体方法**/
public void concreteMethod() {}
public void begin() {
System.out.println("**************************Begin*************************** ");
}
public void end() {
System.out.println("**************************End*************************** ");
}
}
package com.wangmengjun.tutorial.designpattern.template;
public class CsvHanlder extends AbstarctHandler {
@Override
public void validate(String filepath) {
System.out.println("CSV validate ... ... ");
}
@Override
public void parseData(String filepath) {
System.out.println("CSV pasre data ... ... ");
}
@Override
public void display(String filepath) {
System.out.println("CSV dispaly ... ... ");
}
}
PdfHanlder类
package com.wangmengjun.tutorial.designpattern.template;
public class PdfHanlder extends AbstarctHandler {
@Override
public void validate(String filepath) {
System.out.println("PDF validate ... ... ");
}
@Override
public void parseData(String filepath) {
System.out.println("PDF pasre data ... ... ");
}
@Override
public void display(String filepath) {
System.out.println("PDF dispaly ... ... ");
}
}
Excel2003Hanlder类
package com.wangmengjun.tutorial.designpattern.template;
public class Excel2003Hanlder extends AbstarctHandler {
@Override
public void validate(String filepath) {
System.out.println("Excel 2003 validate ... ... ");
}
@Override
public void parseData(String filepath) {
System.out.println("Excel 2003 pasre data ... ... ");
}
@Override
public void display(String filepath) {
System.out.println("Excel 2003 dispaly ... ... ");
}
}
Excel2007Hanlder类
package com.wangmengjun.tutorial.designpattern.template;
public class Excel2007Hanlder extends AbstarctHandler {
@Override
public void validate(String filepath) {
System.out.println("Excel 2007+ validate ... ... ");
}
@Override
public void parseData(String filepath) {
System.out.println("Excel 2007+ pasre data ... ... ");
}
@Override
public void display(String filepath) {
System.out.println("Excel 2007+ dispaly ... ... ");
}
}
package com.wangmengjun.tutorial.designpattern.template;
public class Main {
public static void main(String[] args) {
AbstarctHandler handler = new CsvHanlder();
handler.process("xxx.csv");
System.out.println();
handler = new PdfHanlder();
handler.process("xxx.pdf");
System.out.println();
handler = new Excel2003Hanlder();
handler.process("xxx.xls");
System.out.println();
handler = new Excel2007Hanlder();
handler.process("xxx.xlsx");
}
}
输出结果:
**************************Begin***************************
CSV validate ... ...
CSV pasre data ... ...
CSV dispaly ... ...
**************************End***************************
**************************Begin***************************
PDF validate ... ...
PDF pasre data ... ...
PDF dispaly ... ...
**************************End***************************
**************************Begin***************************
Excel 2003 validate ... ...
Excel 2003 pasre data ... ...
Excel 2003 dispaly ... ...
**************************End***************************
**************************Begin***************************
Excel 2007+ validate ... ...
Excel 2007+ pasre data ... ...
Excel 2007+ dispaly ... ...
**************************End***************************
从上述的输出结果,我们可以看到每个不同类型的处理都具有相同的步骤,但是每个步骤有不同的处理。
模板方法模式 vs. 策略模式
比较
在Template Method模式中,可以使用继承改变程序的行为。这是因为Template Method模式在父类定义程序行为的框架,在子类中决定具体的处理。
与此相对的是Strategy模式,它可以使用委托改变程序的行为。与TemplateMethod模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法。
之前的策略模式博文 -- 策略模式浅析
参考
[1]. https://refactoring.guru/design-patterns/template-method
[2]. 阎宏. Java与模式.电子工业出版社
[3]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.