模板方法设计模式主要是在抽象基类中把算法的骨架定义好,这个是固定的,因此所有的派生类都是固定的算法骨架不可改变,算法中的一部分被延迟到派生类中实现,利用虚函数重写的技术来实现可变部分的重定义,effective c++中的条款35就是描述的模板方法设计模式,其中说明了实现模板方法的三种方式,分别是利用虚函数重写,利用函数指针,利用仿函数对象,这三种方法是实现细节,这里就不展开了,具体的详情可以看effective c++第35条。
简单说模板方法就是抽象基类实现了算法的框架,算法框架中的一些部分需要个性化实现,那么可以根据上面的三种方式进行改变,这里仅拿第一种方法进行举例
具体的元素包括下面部分:
抽象基类:定义了算法的骨架,对象下面代码的TestPaper
派生类:来实现算法中的可变部分,也就是实现具体的细节,对应下面的TestPaperA,和TestPaperB
这里采用大话设计模式中的例子,试卷和每位同学的答案场景来实现模板方法,具体代码看下面
#include <iostream>
#include <string>
using namespace std;
class TestPaper
{
public:
virtual string answer1(){return "";};
virtual string answer2(){return "";};
virtual string answer3(){return "";};
void testQuestion1()
{
cout<<"第一题的问题[ ]\n"<<"A:1\nB:2\nC:3\nD:4\n";
cout<<answer1()<<endl;
}
void testQuestion2()
{
cout<<"第二题的问题[ ]\n"<<"A:1\nB:2\nC:3\nD:4\n";
cout<<answer2()<<endl;
}
void testQuestion3()
{
cout<<"第三题的问题[ ]\n"<<"A:1\nB:2\nC:3\nD:4\n";
cout<<answer3()<<endl;
}
};
class TestPaperA : public TestPaper
{
public:
virtual string answer1(){return "A";};
virtual string answer2(){return "D";};
virtual string answer3(){return "C";};
};
class TestPaperB : public TestPaper
{
public:
virtual string answer1(){return "C";};
virtual string answer2(){return "D";};
virtual string answer3(){return "A";};
};
int main()
{
cout<<"学生甲的试卷:\n";
TestPaper *studentA = new TestPaperA();
studentA->testQuestion1();
studentA->testQuestion2();
studentA->testQuestion3();
cout<<"学生乙的试卷\n";
TestPaper *studentB = new TestPaperB();
studentB->testQuestion1();
studentB->testQuestion2();
studentB->testQuestion3();
delete studentA;
delete studentB;
return 0;
}
模板方法通过把不变行为搬出算法的骨架,去除派生类中的重复代码(基类中是重复的代码),提供了一个很好的代码复用平台,使用场景如下:当不变的和可变的行为在类中混合出现时,可以把多个类中重复的代码独立成一个基类,子类仅实现变化的行为,使得子类避免重复代码的纠缠。