模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

使用背景

  1. 算法骨架固定,但某些步骤可变: 当你有一个算法,其中的某些步骤可能在不同的情况下需要变化,但整体的算法结构是固定的时候,模板方法模式就非常适用。通过在基类中定义算法的骨架,而将一些具体实现延迟到子类中,可以实现代码的复用和扩展。

  2. 避免代码重复: 当多个类中有相似的算法,但其中的一些步骤有所不同时,模板方法模式可以帮助避免重复编写相似的代码。通过将公共的部分提取到基类中,可以减少重复性代码的编写。

  3. 统一管理算法的流程: 使用模板方法模式可以使算法的流程统一管理。通过在基类中定义算法的骨架,可以确保每个子类都按照相同的流程执行算法的各个步骤,从而提高了代码的可维护性和可读性。

  4. 降低耦合度: 模板方法模式可以降低系统中各个类之间的耦合度。基类中定义了算法的骨架,而具体实现延迟到子类中,使得基类和子类之间的耦合度降低,增强了系统的灵活性和可扩展性。

代码实现

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
package main

import "fmt"

// Uploader 抽象类
type Uploader interface {
UploadFile(filename string)
openConnection()
validateUser()
uploadFileContent()
closeConnection()
}

// BaseUploader 具体类,实现 Uploader 接口
type BaseUploader struct{}

func (bu *BaseUploader) UploadFile(filename string) {
fmt.Println("开始上传文件:", filename)
bu.openConnection()
bu.validateUser()
bu.uploadFileContent()
bu.closeConnection()
fmt.Println("文件上传完成")
}

func (bu *BaseUploader) openConnection() {
fmt.Println("打开连接")
}

func (bu *BaseUploader) validateUser() {
fmt.Println("验证用户")
}

func (bu *BaseUploader) uploadFileContent() {
fmt.Println("上传文件内容")
}

func (bu *BaseUploader) closeConnection() {
fmt.Println("关闭连接")
}

// ImageUploader 具体类,继承 BaseUploader
type ImageUploader struct {
BaseUploader
}

func (iu *ImageUploader) uploadFileContent() {
fmt.Println("上传图片文件内容")
}

// VideoUploader 具体类,继承 BaseUploader
type VideoUploader struct {
BaseUploader
}

func (vu *VideoUploader) uploadFileContent() {
fmt.Println("上传视频文件内容")
}

// 客户端代码
func main() {
var uploader Uploader

// 上传图片文件
uploader = &ImageUploader{}
uploader.UploadFile("image.jpg")

fmt.Println()

// 上传视频文件
uploader = &VideoUploader{}
uploader.UploadFile("video.mp4")
}

结语

模板方法模式提供了一种在父类中定义算法骨架,而将具体步骤延迟到子类中实现的方法。这样可以确保算法的结构不变,但具体步骤可以根据需要进行调整。在实际应用中,模板方法模式可以帮助我们避免代码重复,提高代码的可维护性和可扩展性。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。