算法意图:
将算法骨架定义在父类当中,具体的实现放到子类当中。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>
6using namespace std;
7
8class AbstractClass
9{
10public:
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
32protected:
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
42bool AbstractClass::b_jugle = false;
43
44
45void AbstractClass::doFirst()
46{
47 cout<<"do std before"<<endl;
48}
49
50void AbstractClass::doAfter()
51{
52 cout<<"do std after"<<endl;
53}
54
55// 继承自AbstractClass,实现算法
56class ConcreateClass: public AbstractClass
57{
58public:
59 ConcreateClass(){}
60 virtual ~ConcreateClass(){}
61
62protected:
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,实现算法
79class ConcreateClassNew: public AbstractClass
80{
81public:
82 ConcreateClassNew(){}
83 virtual ~ConcreateClassNew(){}
84
85protected:
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
102int _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. 好莱坞原则:别调用我们,在我们需要时会调用你
最后谈一下和策略模式的区别,最主要的区别是一个是使用继承而策略模式是使用组合方式。