设计模式-模板方法模式

Template Method

模板方法模式是在 superclass 中定义算法框架,允许子类在不修改结构情况下重写算法特定步骤

  • 当算法/对象可以分解为多个步骤实现,其中仅部分步骤存在差异或需要进行扩展时,可以采用该模式
  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则

CPP

基本结构

Member FullName Description
抽象类 Abstract­ Class 定义算法的骨架(模板方法)和必要的抽象方法
具体子类 Concrete­ Class 实现抽象类中的具体步骤,定制行为
模板方法 Template Method 在抽象类中定义,不允许子类修改
  1. 定义抽象类 (包含模板方法)
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
class Calculator {
public:
// 模板方法,定义算法骨架
void runProcess() {
initialize(); // 初始化
stepOne(); // 步骤1
stepTwo(); // 步骤2
finalize(); // 结束
}

protected:
// 默认实现的初始化步骤
virtual void initialize() {
std::cout << "Initializing Calculator\n";
}

// 必须由子类实现的虚函数
virtual void stepOne() = 0;

// 必须由子类实现的虚函数
virtual void stepTwo() = 0;

// 默认实现的结束步骤
virtual void finalize() {
std::cout << "Finalizing Calculator\n";
}
};
  1. 定义具体子类
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
class AddCalculator : public Calculator {
int num1, num2;

protected:
void stepOne() override {
num1 = 5;
num2 = 3;
std::cout << "Adding numbers: " << num1 << " + " << num2 << " = ";
}
void stepTwo() override {
std::cout << num1 + num2 << "\n";
}
};

class MultiplyCalculator : public Calculator {
int num1, num2;

protected:
void stepOne() override {
num1 = 5;
num2 = 3;
std::cout << "Multiplying numbers: " << num1 << " * " << num2 << " = ";
}

void stepTwo() override {
std::cout << num1 * num2 << "\n";
}
};
  1. 调用模板类
1
2
3
4
5
6
7
8
Calculator* addCalc = new AddCalculator();
addCalc->runProcess();

Calculator* mulCalc = new MultiplyCalculator();
mulCalc->runProcess();

delete addCalc;
delete mulCalc;

Fortran

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module calculator_mod
implicit none

type, abstract :: Calculator
contains
procedure :: initialize => initialize_default
procedure(calculator_step_one), deferred :: stepOne
procedure(calculator_step_two), deferred :: stepTwo
procedure :: finalize => finalize_default
procedure :: runProcess
end type Calculator

abstract interface
subroutine calculator_step_one(this)
import :: Calculator
class(Calculator) :: this
end subroutine calculator_step_one

subroutine calculator_step_two(this)
import :: Calculator
class(Calculator) :: this
end subroutine calculator_step_two
end interface

contains

subroutine initialize_default(this)
class(Calculator) :: this
print *, "Initializing Calculator"
end subroutine initialize_default

subroutine finalize_default(this)
class(Calculator) :: this
print *, "Finalizing Calculator"
end subroutine finalize_default

subroutine runProcess(this)
class(Calculator) :: this

call this%initialize()
call this%stepOne()
call this%stepTwo()
call this%finalize()
end subroutine runProcess

end module calculator_mod

module add_multiply_calculators_mod
use calculator_mod
implicit none

type, extends(Calculator) :: AddCalculator
integer :: num1, num2
contains
procedure :: stepOne => add_step_one
procedure :: stepTwo => add_step_two
end type AddCalculator

type, extends(Calculator) :: MultiplyCalculator
integer :: num1, num2
contains
procedure :: stepOne => multiply_step_one
procedure :: stepTwo => multiply_step_two
end type MultiplyCalculator

contains

subroutine add_step_one(this)
class(AddCalculator) :: this

this%num1 = 5
this%num2 = 3
print *, "Adding numbers: ", this%num1, " + ", this%num2, " = "
end subroutine add_step_one

subroutine add_step_two(this)
class(AddCalculator) :: this
print *, this%num1 + this%num2
end subroutine add_step_two

subroutine multiply_step_one(this)
class(MultiplyCalculator) :: this

this%num1 = 5
this%num2 = 3
print *, "Multiplying numbers: ", this%num1, " * ", this%num2, " = "
end subroutine multiply_step_one

subroutine multiply_step_two(this)
class(MultiplyCalculator) :: this
print *, this%num1 * this%num2
end subroutine multiply_step_two

end module add_multiply_calculators_mod

program main
use calculator_mod
use add_multiply_calculators_mod
implicit none

class(Calculator), pointer :: addCalc, mulCalc

allocate(AddCalculator :: addCalc)
allocate(MultiplyCalculator :: mulCalc)

call addCalc%runProcess()
call mulCalc%runProcess()

deallocate(addCalc)
deallocate(mulCalc)

end program main

Reference

refactoringguru | 模板方法模式
阿里云 | CPP模板方法模式

0%