概述
模板方法模式,英文是template method pattern,说起模板,我们都不陌生,比如,写论文按照引言,摘要,正文,结论等模板来写,同时生活中各处都存在着模块,做PPT,按照模板来,我们只管填充内容,同样,在软件设计中,我们按照一定的模板来设计就可以成为模板方法模式,但是注意,这里的模板和c++中的template和java的泛型不是那么一回事,这里更强调的是按照一定的结构(模板)来处理问题。
在英文中,模板方法模式的描述如下:
In software engineering, the template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, deferring some steps to subclasses.It lets one redefine certain steps of an algorithm without changing the algorithm’s structure.
可以看出,这里强调的是定义一种包含若干步骤的算法程序框架,并且这种框架允许别人重新定义具体的步骤内容,但不改变算法的整体结构。
具体实现
模板方法模式结构
模板方法非常的简单,UML如下:
我们可以看到,模板方法基本包含两个部分:
1. 抽象模板
抽象模板定义了整体的框架,包含一个或多个操作步骤,并存在一个模板方法,该方法中具体定义了操作步骤执行顺序,如上图中的TemplateMethod。
2. 具体模板
实现抽象模板中具体的抽象方法,不同的具体模板可以有不同的实现。
模板方法依赖的关键在于:在继承层次中,子类的函数实现可以覆盖父类的函数实现(除非定义为final),子类不能再决定执行步骤,但是可以决定具体的每步骤执行内容。
具体实现说明
模板方法模式中定义了一系列方法,主要包括模板方法和其他的方法,从逻辑上来说,其他方法可以是普通的方法(已经实现),抽象的方法(待子类实现)或者钩子方法(父类实现,子类可扩展重写)
关于不同函数的说明:
- 抽象方法
java中抽象方法用关键字abstract声明,父类只声明,由子类定义如何实现。 - 具体方法
- 抽象类实现方法要做的事,子类不实现;
- 钩子方法
钩子函数,即Hook Method,钩子方法由抽象类声明并实现作为默认的实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现;另外注意的是,一般钩子方法的命名都是以do开头,这不是必须的,但是规范的命名让别人更清楚。
另外,钩子方法在实际应用中也可以由另一种用法,即通过isXXX函数和doXXX函数配合,由子类决定是否执行该步骤,这时候也可以认为这个是钩子方法。
实现示例
比如,我们在实际互联网工程中,经常要处理网络请求,假如我们现在规定处理请求的步骤为4步:启动初始化,处理请求,打印结果,构造返回值,如果用模板方法模式来设计,代码实现如下:
public abstract class AbstractRequestProcessor {
protected String request; // 为了简便,request只为string类型
protected String response; // 返回值
// 钩子函数,子类可决定是否执行初始化
public void doSetUp() { }
public abstract void subProcess();
public abstract String buildResponse();
public abstract boolean isPrintResponse();
public void doPrint() {
System.out.println(response);
}
// 模板方法
public String process(String request) {
this.request = request;
doSetUp();
subProcess();
if (isPrintResponse()) {
doPrint();
}
buildResponse();
return response;
}
}
// 转化为大写
public class UpperProcessor extends AbstractRequestProcessor {
public void subProcess() {
if (request != null) {
this.response = request.toUpperCase();
}
}
public String buildResponse() {
String ret = "";
if (response != null) {
ret = response;
}
return ret;
}
public boolean isPrintResponse() {
if (response != null) {
return true;
}
return false;
}
}
以上,就是模板方法模式,这也是非常常用的一种模式。