Fork me on GitHub

【设计模式】模板方法模式

封面

什么是模板方法模式

在计算机程序中,为了将一些具有不同实现但有相同执行步骤的类统一起来,通常我们将这些类抽象成一个模板类。模板类定义了一个算法的框架,使得子类可以不改变算法的结构而去对一些细节实现进行重新定义。

模板方法模式的核心要素

抽象模板

抽象模板中定义了两种方法:需要子类去实现的基本方法,以及固定的不需要子类去实现的具体算法步骤的模板方法。基本方法在模板方法中被调用,模板方法一般会是一个具体的算法框架,调度基本方法完成所有功能。

具体实现

子类具体实现抽象模板中的基本方法,完成对框架中的算法细节进行重新定义。

我在实际项目中使用的案例

在做某个按需查询不同类别的用户,并将其上传到OSS上,每日发邮件告诉运营人员结果的一个需求的时候,我就用到了模板方法模式。
首先定义一个抽象模板,分别有查询用户(每天都不同的SQL),上传到OSS,发邮件等几个步骤,即基本方法。在模板方法中将这几个步骤封装起来。定义7个子类分别对每天不同的查询、上传、邮件做具体的实现。最后根据策略模式,不同的星期调用不同的对象的模板方法完成核心功能。

模板方法模式代码示例

如图,有个做饭的抽象模板:定义了[洗菜-炒菜-完成]三个步骤为基本方法,一个ComplateCook方法完成步骤的组装

抽象模板

一个西红柿炒蛋的实现类

子类1

一个鱼香肉丝的实现类

子类2

具体代码如下:

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
public abstract class CookTemplate {

// 定义步骤为抽象方法

public abstract void wash();

public abstract void cook();

public abstract void finish();

public final void ComplateCook() {
System.out.println("开始做菜~");
wash();
cook();
finish();
System.out.println("完成做菜步骤~");
}
}
public class XihongshiChaoEgg extends CookTemplate{
@Override
public void wash() {
System.out.println("切西红柿,准备鸡蛋~");
}

@Override
public void cook() {
System.out.println("炒鸡蛋,然后再炒西红柿~");
}

@Override
public void finish() {
System.out.println("西红柿炒蛋做好了,出锅~");
}
}
public class YuXiangRose extends CookTemplate{
@Override
public void wash() {
System.out.println("洗胡萝卜~");
System.out.println("切肉丝~");
}

@Override
public void cook() {
System.out.println("开始做鱼香肉丝~");
}

@Override
public void finish() {
System.out.println("鱼香肉丝做好了 出锅~");
}
}
public class Client {

public static void main(String[] args) {
CookTemplate cook = new XihongshiChaoEgg();
cook.ComplateCook();
cook = new YuXiangRose();
cook.ComplateCook();
}
}

模板方法模式优缺点

  • 优点

    • 封装了不可变的部分,扩展可变部分
    • 提供公共代码,便于维护
    • 具体行为父类控制,子类只管自己的细节实现,符合开闭原则
  • 缺点

    • 一个不同的实现都要增加一个子类,会导致代码量很庞大
    • 父类的执行结果会受到子类的影响,在复杂代码的阅读中会给开发人员带来很多麻烦

总结

模板方法模式适用于:有一个固定的算法步骤,但是细节实现存在多种可能的场景,即整体稳定但是个别易变的时候讲会变化的那一部分抽象出来。
模板方法模式强调抽象类与子类之间的协作,它将调用权交给父类,是一种控制反转的设计理念。子类不再去完成核心的功能,只需要关注属于自己的那一部分的实现。


  • JDK中经典的模板方法模式实现:AQS
陈年风楼 wechat
Add my WeChat, share tech-skills to each other 🙆‍