1、定义了一个操作中的算法的骨架,而将一些步骤延迟到了子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
当我们要完成在某一细节层次一致的一个过程或一系列步骤,但某个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法来处理。
UML图如下:
2、 AbstractClass是抽象类,其实也就是一抽象模板,定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
ConcreteClass,实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
3、模板方法模式特点
模板方法模式是通过把不变行为搬移到超类,去除了子类中的重复代码来体现它的优势。提供了一个很好的代码复用平台。因为有时候,我们会遇到由一系列步骤构成的过程需要执行。这个过程从高层次上看是相同的,但是有些步骤的实现可能不同。这时候,我们通常就应该要考虑用模板方法模式了。
“当不变的和变化的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复不变行为的纠缠”。
4、C++代码实现
- #include <iostream>
- using namespace std;
- //抽象接口类定义了算法的执行步骤框架
- class AbstractClass
- {
- public:
- virtual void Operation1() = 0;
- virtual void Operation2() = 0;
- void TemplateMethod() {
- Operation1();
- Operation2();
- }
- };
- //具体类A,实现算法的步骤的特定操作
- class ConcreteClassA : public AbstractClass
- {
- public:
- void Operation1() {
- cout << "具体类A方法1实现" << endl;
- }
- void Operation2() {
- cout << "具体类A方法2实现" << endl;
- }
- };
- //具体类B,实现算法的步骤的特定操作
- class ConcreteClassB : public AbstractClass
- {
- public:
- void Operation1() {
- cout << "具体类B方法1实现" << endl;
- }
- void Operation2() {
- cout << "具体类B方法2实现" << endl;
- }
- };
- int main()
- {
- AbstractClass * p_abstractClass = new ConcreteClassA();
- p_abstractClass->TemplateMethod();
- delete p_abstractClass;
- p_abstractClass = new ConcreteClassB();
- cout << endl;
- p_abstractClass->TemplateMethod();
- delete p_abstractClass;
- p_abstractClass = NULL;
- return 0;
- }
在举一个实际的例子
最近有个招聘会,可以带上简历去应聘了。但是,其中有一家公司不接受简历,而是给应聘者发了一张简历表,上面有基本信息、教育背景、工作经历等栏,让应聘者按照要求填写完整。每个人拿到这份表格后,就开始填写。如果用程序实现这个过程,该如何做呢?一种方案就是用模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。我们的例子中,操作就是填写简历这一过程,我们可以在父类中定义操作的算法骨架,而具体的实现由子类完成。下面给出它的UML图。
其中FillResume() 定义了操作的骨架,依次调用子类实现的函数。相当于每个人填写简历的实际过程。接着给出相应的C++代码。
- //简历
- class Resume
- {
- protected: //保护成员
- virtual void SetPersonalInfo() {}
- virtual void SetEducation() {}
- virtual void SetWorkExp() {}
- public:
- void FillResume()
- {
- SetPersonalInfo();
- SetEducation();
- SetWorkExp();
- }
- };
- class ResumeA: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"A's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"A's Education"<<endl; }
- void SetWorkExp() { cout<<"A's Work Experience"<<endl; }
- };
- class ResumeB: public Resume
- {
- protected:
- void SetPersonalInfo() { cout<<"B's PersonalInfo"<<endl; }
- void SetEducation() { cout<<"B's Education"<<endl; }
- void SetWorkExp() { cout<<"B's Work Experience"<<endl; }
- };
使用方式如下:
- int main()
- {
- Resume *r1;
- r1 = new ResumeA();
- r1->FillResume();
- delete r1;
- r1 = new ResumeB();
- r1->FillResume();
- delete r1;
- r1 = NULL;
- return 0;
- }