模板方法模式是一种十分常见的设计模式,阅读源码是可以说是处处可见。在日常的工作代码编写中也经常使用。这里来记录一下。模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。

模板方法模式

这个设计模式的主要思想是当某个方法中一部分具有重复性时,可以将重复部分代码提取在父类中实现,而将变化的部分延迟至子类中实现。
基本类代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public abstract class AbstractClass {
protected abstract void doAnything();
protected abstract void doSomething();
public final void templateMethod(){
/*
* 调用基本方法,完成相关的逻辑
*/
this.doAnything();
this.doSomething();
}
}
public class ConcreteClass1 extends AbstractClass {

@Override
protected void doAnything() {
// TODO Auto-generated method stub
//子类实现具体
}

@Override
protected void doSomething() {
// TODO Auto-generated method stub
}
}
public class ConcreteClass2 extends AbstractClass {

@Override
protected void doAnything() {
// TODO Auto-generated method stub
//子类实现具体
}

@Override
protected void doSomething() {
// TODO Auto-generated method stub
}
}

public static void main (){
AbstractClass a = new ConcreteClass1();
AbstractClass b = new ConcreteClass2();
a.templateMethod();
b.templateMethod();
}

实际应用

旧代码

最近调到了新部门,发现后台Service层代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protected void doAction(RequestBean requestBean, ResponseBean responseBean) throws Exception     {
// 获取参数集合
Map sysMap = requestBean.getSysMap();
// 获取操作标识
String oper_type = (String) sysMap.get("oper_type");
if (AOSConstants.OPERATE_QUERY.equals(oper_type)) {
// 查询
queryOperation(requestBean,responseBean);
} else if (AOSConstants.OPERATE_MODIFY.equals(oper_type)) {
// 修改操作
modifOperation(requestBean,responseBean);
} else if (AOSConstants.OPERATE_ADD.equals(oper_type)) {
// 新增
addOperation(requestBean,responseBean);
} else if (AOSConstants.OPERATE_DELETE.equals(oper_type)) {
// 删除
deleteOperation(requestBean,responseBean);
} else if ("query_flow".equals(oper_type)){
// 查询明细
queryDetailOperation(requestBean,responseBean);
} else if ("sel_user".equals(oper_type)) {
// 角色下拉框初始化
roleInfo(requestBean, responseBean);
} else if ("sel_elem".equals(oper_type)) {
// 查询要素
selectElems(requestBean, responseBean);
}
}

可以看到,Service层处理业务逻辑时是根据前端传过来的参数去调用不同方法,而增删改查部分的操作标志是固定不变的。这就意味着需要每次去编写相同的条件判断语句,十分不简洁。于是就想到了可以使用模板方法模式+内部类来进行改写。

改进代码

可以在模板类中定义类似于doAction中的算法骨架,然后在Service中生成匿名类去定义变化部分的方法实现:

模板类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public abstract class TemplateService {

// 日志记录器
protected Logger logger = LoggerFactory.getLogger(getClass());

private static final String OPERTYPE = "oper_type";

//模板方法,定义算法骨架
public void operate(RequestBean requestBean, ResponseBean responseBean) throws Exception {
// 获取参数集合
Map sysMap = requestBean.getSysMap();
// 获取操作标识
String operateType = (String) sysMap.get(OPERTYPE);
if (BaseUtil.isBlank(operateType)) {
logger.error("参数{}为空", OPERTYPE);
// TODO: 2018/6/13 异常定义
throw new Exception();
}
switch (operateType) {
case AOSConstants.OPERATE_QUERY:
operateQuery(requestBean, responseBean, operateType);
break;
case AOSConstants.OPERATE_MODIFY:
operateModify(requestBean, responseBean, operateType);
break;
case AOSConstants.OPERATE_ADD:
operateAdd(requestBean, responseBean, operateType);
break;
case AOSConstants.OPERATE_DELETE:
operateDelete(requestBean, responseBean, operateType);
break;
default:
operateOther(requestBean, responseBean, operateType);
}
}


// 更新操作
public abstract void operateModify(RequestBean requestBean, ResponseBean responseBean, String operateType);

//查询操作
public abstract void operateQuery(RequestBean requestBean, ResponseBean responseBean, String operateType);

//新增操作
public abstract void operateAdd(RequestBean requestBean, ResponseBean responseBean, String operateType);

//删除操作
public abstract void operateDelete(RequestBean requestBean, ResponseBean responseBean, String operateType);

//其他操作
public abstract void operateOther(RequestBean requestBean, ResponseBean responseBean, String operateType);

}

Service代码优化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected void doAction(RequestBean requestBean, ResponseBean responseBean) throws Exception {
//实例化匿名内部类 去定义实际的操作
new TemplateService(){
@Override
public void operateModify(RequestBean requestBean, ResponseBean responseBean, String operateType) {

}
@Override
public void operateQuery(RequestBean requestBean, ResponseBean responseBean, String operateType) {
queryOrganl(requestBean, responseBean);
}
@Override
public void operateAdd(RequestBean requestBean, ResponseBean responseBean, String operateType) {

}
@Override
public void operateDelete(RequestBean requestBean, ResponseBean responseBean, String operateType) {

}
@Override
public void operateOther(RequestBean requestBean, ResponseBean responseBean, String operateType) {

}
}.operate(requestBean, responseBean);
}

这次的代码优化其实有点强行使用设计模式的意思,但是却也是对设计模式的一次应用,加强了对其的理解