算法意图:
将算法骨架定义在父类当中,具体的实现放到子类当中。Template method可以不改变算法的骨架在子类中重新定义算法中的某些特定的步骤。
算法适用性:
1. 一次性将算法的不变部分封装到父类当中,将可变的部分放到子类中去实现。
2. 各子类的公共部分亚冠提取出来放到父类当中,避免代码重复,分离变化和不变的地方。
3. 通过hook来控制子类的扩展。
4. 模板方法的格式:
class TemplateMethod_Demo
{
public:
<返回值类型> <模板方法名>(<参数列表>); //模板方法成员函数,定义为公有的非虚成员函数,供客户调用;
protected:
virtual <返回值类型> <抽象操作的方法名>(<参数列表>) = 0;//抽象操作(可选),即:原语操作,用纯虚函数表示,必须被重定义,定义为保护类型的,只能被模板方法本身调用;
virtual <返回值类型> <钩子操作的方法名>(<参数列表>){}; //钩子操作(必选),即:原语操作,用虚函数表示,可被重定义,提供缺省实现,定义为保护类型的,只能被模板方法本身调用;
};
1
// template.cpp : 定义控制台应用程序的入口点。
2
//
3
4
#include "stdafx.h"
5
#include<iostream>
6
using namespace std;
7
8
class AbstractClass
9

{
10
public:
11
AbstractClass()
{}
12
virtual ~AbstractClass()
{}
13
virtual void doFirst();
14
virtual void doAfter();
15
// 这个函数中定义了算法的轮廓
16
void TemplateMethod()
17
{
18
doFirst();
19
PrimitiveOperation1();
20
PrimitiveOperation2();
21
if (b_jugle)
22
{
23
doSthElse();
24
}
25
doAfter();
26
}
27
virtual void setHookTrue()
28
{
29
AbstractClass::b_jugle = true;
30
};
31
32
protected:
33
// 纯虚函数,由派生类实现之
34
virtual void PrimitiveOperation1() = 0;
35
virtual void PrimitiveOperation2() = 0;
36
virtual void doSthElse() = 0;
37
static bool b_jugle;
38
39
40
};
41
42
bool AbstractClass::b_jugle = false;
43
44
45
void AbstractClass::doFirst()
46

{
47
cout<<"do std before"<<endl;
48
}
49
50
void AbstractClass::doAfter()
51

{
52
cout<<"do std after"<<endl;
53
}
54
55
// 继承自AbstractClass,实现算法
56
class ConcreateClass: public AbstractClass
57

{
58
public:
59
ConcreateClass()
{}
60
virtual ~ConcreateClass()
{}
61
62
protected:
63
virtual void PrimitiveOperation1()
64
{
65
cout << "PrimitiveOperation1 by ConcreateClass\n";
66
}
67
virtual void PrimitiveOperation2()
68
{
69
cout << "PrimitiveOperation2 by ConcreateClass\n";
70
}
71
virtual void doSthElse()
72
{
73
cout<<"so something else!\n"<<endl;
74
}
75
};
76
77
78
// 继承自AbstractClass,实现算法
79
class ConcreateClassNew: public AbstractClass
80

{
81
public:
82
ConcreateClassNew()
{}
83
virtual ~ConcreateClassNew()
{}
84
85
protected:
86
virtual void PrimitiveOperation1()
87
{
88
cout << "PrimitiveOperation1 by ConcreateClassNew\n";
89
}
90
virtual void PrimitiveOperation2()
91
{
92
cout << "PrimitiveOperation2 by ConcreateClassNew\n";
93
}
94
virtual void doSthElse()
95
{
96
cout<<"so something else!\n"<<endl;
97
}
98
99
};
100
101
102
int _tmain(int argc, _TCHAR* argv[])
103

{
104
AbstractClass* pConcreateClass = new ConcreateClass;
105
pConcreateClass->TemplateMethod();
106
delete pConcreateClass;
107
108
109
AbstractClass* pConcreateClass2 = new ConcreateClassNew;
110
pConcreateClass2->setHookTrue();
111
pConcreateClass2->TemplateMethod();
112
delete pConcreateClass2;
113
return 0;
114
}
115
116
运行结果:
template method的设计原则:
1.封装变化部分;
2.对接口编程
3. 好莱坞原则:别调用我们,在我们需要时会调用你
最后谈一下和策略模式的区别,最主要的区别是一个是使用继承而策略模式是使用组合方式。