模板设计模式(Template)

行为型模式

模板方法模式通常又叫模板模式,是指定义一个算法的骨架,并允许之类为其中的一个或者多个步骤提供实现。模板方法模式使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

角色

模板方法(Template Method)模式包含以下主要角色:

  • 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
    • 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
    • 基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:
      • 抽象方法(Abstract Method) :一个抽象方法由抽象类声明、由其具体子类实现。
      • 具体方法(Concrete Method) :一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
      • 钩子方法(Hook Method) :在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值类型为boolean类型。
  • 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。

代码实现

fold
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
// 抽象类
public abstract class DayOffProcess {
// 请假模板 模板方法:提供模板的调用顺序
public final void dayOffProcess() {
// 领取申请表
this.pickUpForm();
// 填写申请信息
this.writeInfo();
// 签名
this.signUp();
// 提交到不同部门审批
this.summit();
// 行政部备案
this.filing();
}
// 具体方法
private void filing() {
System.out.println("行政部备案");
}
// 抽象方法
protected abstract void summit();
protected abstract void signUp();
private void writeInfo() {
System.out.println("填写申请信息");
}
private void pickUpForm() {
System.out.println("领取申请表");
}
}
// 具体子类
public class ZhangSan extends DayOffProcess {
@Override
protected void summit() {
System.out.println("张三签名");
}
@Override
protected void signUp() {
System.out.println("提交到技术部审批");
}
}
public class Lisi extends DayOffProcess {
@Override
protected void summit() {
System.out.println("李四签名");
}
@Override
protected void signUp() {
System.out.println("提交到市场部审批");
}
}
// 测试方法
public static void main(String[] args) {
DayOffProcess zhangsan = new ZhangSan();
//领取申请表
//填写申请信息
//提交到技术部审批
//张三签名
//行政部备案
zhangsan.dayOffProcess();
DayOffProcess lisi = new Lisi();
//领取申请表
//填写申请信息
//提交到市场部审批
//李四签名
//行政部备案
lisi.dayOffProcess();
}

总结

适用场景:

  • 一次性实现一个算法不变的部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。

优点:

  • 利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
  • 将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
  • 把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。

缺点:

  • 类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
  • 类数量的增加,间接地增加了系统实现的复杂度。
  • 继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。