设计模式 | 模板方法 (Template Method)
What
- 父类定义处理流程的框架,子类实现流程中各个功能的具体细节。
- 设计原则:Do not call me, I will call you.
How
UML 图
代码
以我们日常工作的日程安排为例
定义父类 Worker,里面定义了框架流程方法 dailyRountine:
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78package one.wangwei.designpatterns.templatemethod;
import lombok.extern.slf4j.Slf4j;
public abstract class Worker {
/**
* 每日日程安排
*/
public void dailyRountine() {
String name = getName();
getUp(name);
eatBreakfast(name);
goToWork(name);
work(name);
goBackHome(name);
relax(name);
sleep(name);
System.out.println("\n");
}
/**
* 获取姓名
*
* @return
*/
protected abstract String getName();
/**
* 起床
*/
public void getUp(String name) {
log.info("{} 起床了", name);
}
/**
* 吃早餐
*/
public void eatBreakfast(String name) {
log.info("{} 吃早餐", name);
}
/**
* 去上班
*/
public void goToWork(String name) {
log.info("{} 要去上班了", name);
}
/**
* 工作
*/
protected abstract void work(String name);
/**
* 下班回家
*/
public void goBackHome(String name) {
log.info("{} 忙完工作,下班回家了", name);
}
/**
* 放松休息
*/
public void relax(String name) {
log.info("{} 看美剧,放松一下", name);
}
/**
* 入睡
*/
public void sleep(String name) {
log.info("{} 开始睡觉了", name);
}
}定义子类 ProductManager,实现抽象方法:
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
34package one.wangwei.designpatterns.templatemethod;
import lombok.extern.slf4j.Slf4j;
/**
* 产品经理
*
* @author wangwei
* @date 2018/05/08
*/
public class ProductManager extends Worker {
/**
* 获取姓名
*
* @return
*/
protected String getName() {
return "小伟";
}
/**
* 工作
*
* @param name
*/
protected void work(String name) {
log.info("{} 是位产品经理,主要的工作就是画产品原型", name);
}
}定义子类 Programmer,实现抽象方法:
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
44package one.wangwei.designpatterns.templatemethod;
import lombok.extern.slf4j.Slf4j;
/**
* 程序员
*
* @author wangwei
* @date 2018/05/08
*/
public class Programmer extends Worker {
/**
* 获取姓名
*
* @return
*/
protected String getName() {
return "小明";
}
/**
* 工作
*
* @param name
*/
protected void work(String name) {
log.info("{} 是名程序猿,主要的工作是编写程序", name);
}
/**
* 放松休息
*
* @param name
*/
public void relax(String name) {
log.info("{} 喜欢跑步来放松心情", name);
}
}定义子类 UIDesigner,实现抽象方法:
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
44package one.wangwei.designpatterns.templatemethod;
import lombok.extern.slf4j.Slf4j;
/**
* UI 设计师
*
* @author wangwei
* @date 2018/05/08
*/
public class UIDesigner extends Worker {
/**
* 获取姓名
*
* @return
*/
protected String getName() {
return "小美";
}
/**
* 工作
*
* @param name
*/
protected void work(String name) {
log.info("{} 是位UI设计师,每天的工作主要是设计UI界面", name);
}
/**
* 放松休息
*
* @param name
*/
public void relax(String name) {
log.info("{} 喜欢看韩剧来放松心情", name);
}
}定义调用类 WorkerHelper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package one.wangwei.designpatterns.templatemethod;
public class WorkerHelper {
private Worker worker;
public WorkerHelper(Worker worker) {
this.worker = worker;
}
public void changeWorker(Worker worker) {
this.worker = worker;
}
public void dailyRountine() {
this.worker.dailyRountine();
}
}运行
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
46package one.wangwei.designpatterns.templatemethod;
public class App {
public static void main(String[] args) {
WorkerHelper workerHelper = new WorkerHelper(new ProductManager());
workerHelper.dailyRountine();
workerHelper.changeWorker(new Programmer());
workerHelper.dailyRountine();
workerHelper.changeWorker(new UIDesigner());
workerHelper.dailyRountine();
}
}
// 输出如下信息:
14:58:27.835 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 起床了
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 吃早餐
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 要去上班了
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.ProductManager - 小伟 是位产品经理,主要的工作就是画产品原型
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 忙完工作,下班回家了
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 看美剧,放松一下
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小伟 开始睡觉了
14:58:27.842 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小明 起床了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小明 吃早餐
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小明 要去上班了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Programmer - 小明 是名程序猿,主要的工作是编写程序
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小明 忙完工作,下班回家了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Programmer - 小明 喜欢跑步来放松心情
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小明 开始睡觉了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小美 起床了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小美 吃早餐
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小美 要去上班了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.UIDesigner - 小美 是位UI设计师,每天的工作主要是设计UI界面
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小美 忙完工作,下班回家了
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.UIDesigner - 小美 喜欢看韩剧来放松心情
14:58:27.843 [main] INFO one.wangwei.designpatterns.templatemethod.Worker - 小美 开始睡觉了
JDK 中的运用
- java.io.InputStream , java.io.OutputStream , java.io.Reader 以及 java.io.Writer 中所有非抽象方法;
- java.util.AbstractList , java.util.AbstractSet 以及 java.util.AbstractMap 中所有非抽象方法;
- javax.servlet.http.HttpServlet 中 默认发送 Http 405 “Method Not Allowed” 错误响应信息的 doXXX () 的方法;
参考资料
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment