C++设计模式编程中Template Method模板方法模式的运用
准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模版方法模式的用意。
很多人可能没有想到,模版方法模式实际上是所有模式中最为常见的几个模式之一,而且很多人可能使用过模版方法模式而没有意识到自己已经使用了这个模式。模版方法模式是基于继承的代码复用的基本技术,模版方法模式的结构和用法也是面向对象设计的核心。
模版方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitive method);而将这些基本法方法总汇起来的方法叫做模版方法(template method),这个设计模式的名字就是从此而来。
模版方法模式中的方法
模版方法中的方法可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。
模版方法
一个模版方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模版方法一般会在抽象类中定义,并由子类不加以修改地完全继承下来。
基本方法
基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。
- 抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在C#语言里一个抽象方法以abstract关键字标示出来。
- 具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。在C#语言里面,一个具体方法没有abstract关键字。
- 钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。(Visual FoxPro中项目向导建立的项目会使用一个AppHook类实现监视项目成员变化,调整系统结构的工作。)钩子方法的名字通常以do开始。
模板方法模式的实现
完整代码示例(code):模板方法模式的实现很简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用 C++实现,并在 VC 6.0 下测试运行)。
代码片断 1:Template.h
//Template.h #ifndef _TEMPLATE_H_ #define _TEMPLATE_H_ class AbstractClass{ public: virtual ~AbstractClass(); void TemplateMethod(); protected: virtual void PrimitiveOperation1() = 0; virtual void PrimitiveOperation2() = 0; AbstractClass(); private: }; class ConcreteClass1:public AbstractClass{ public: ConcreteClass1(); ~ConcreteClass1(); protected: void PrimitiveOperation1(); void PrimitiveOperation2(); private: }; class ConcreteClass2:public AbstractClass{ public: ConcreteClass2(); ~ConcreteClass2(); protected: void PrimitiveOperation1(); void PrimitiveOperation2(); private: }; #endif //~_TEMPLATE_H_
代码片断 2:Template.cpp
#include "Template.h" #include <iostream> using namespace std; AbstractClass::AbstractClass(){ } AbstractClass::~AbstractClass(){ } void AbstractClass::TemplateMethod(){ this->PrimitiveOperation1(); this->PrimitiveOperation2(); } ConcreteClass1::ConcreteClass1(){ } ConcreteClass1::~ConcreteClass1(){ } void ConcreteClass1::PrimitiveOperation1(){ cout<<"ConcreteClass1...PrimitiveOperat ion1"<<endl; } void ConcreteClass1::PrimitiveOperation2(){ cout<<"ConcreteClass1...PrimitiveOperat ion2"<<endl; } ConcreteClass2::ConcreteClass2(){ } ConcreteClass2::~ConcreteClass2(){ } void ConcreteClass2::PrimitiveOperation1(){ cout<<"ConcreteClass2...PrimitiveOperat ion1"<<endl; } void ConcreteClass2::PrimitiveOperation2(){ cout<<"ConcreteClass2...PrimitiveOperat ion2"<<endl; }
代码片断 3:main.cpp
#include "Template.h" #include <iostream> using namespace std; int main(int argc,char* argv[]){ AbstractClass* p1 = new ConcreteClass1(); AbstractClass* p2 = new ConcreteClass2(); p1->TemplateMethod(); p2->TemplateMethod(); return 0; }
代码说明:由于模板方法模式的实现代码很简单,因此解释是多余的。其关键是将通用算法(逻辑)封装起来,而将算法细节让子类实现(多态)。
唯一注意的是我们将原语操作(细节算法)定义未保护(Protected)成员,只供模板方法调用(子类可以)。
适用场景
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是O p d y k e 和J o h n s o n 所描述过的“重分解以一般化”的一个很好的例子[ O J 9 3 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
控制子类扩展。模板方法只在特定点调用“h o o k ”操作(参见效果一节),这样就只允许在这些点进行扩展。
您可能感兴趣的文章
- 04-02c语言没有round函数 round c语言
- 01-10深入理解C++中常见的关键字含义
- 01-10使用C++实现全排列算法的方法详解
- 01-10c++中inline的用法分析
- 01-10用C++实现DBSCAN聚类算法
- 01-10全排列算法的非递归实现与递归实现的方法(C++)
- 01-10C++大数模板(推荐)
- 01-10浅谈C/C++中的static与extern关键字的使用详解
- 01-10深入C/C++浮点数在内存中的存储方式详解
- 01-10深入理解C/C++混合编程
阅读排行
本栏相关
- 04-02c语言函数调用后清空内存 c语言调用
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言的正则匹配函数 c语言正则表达
- 04-02c语言用函数写分段 用c语言表示分段
- 04-02c语言中对数函数的表达式 c语言中对
- 04-02c语言编写函数冒泡排序 c语言冒泡排
- 04-02c语言没有round函数 round c语言
- 04-02c语言分段函数怎么求 用c语言求分段
- 04-02C语言中怎么打出三角函数 c语言中怎
- 04-02c语言调用函数求fibo C语言调用函数求
随机阅读
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 01-10SublimeText编译C开发环境设置
- 04-02jquery与jsp,用jquery
- 08-05织梦dedecms什么时候用栏目交叉功能?
- 01-11ajax实现页面的局部加载
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 01-10C#中split用法实例总结
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 01-10delphi制作wav文件的方法
- 08-05DEDE织梦data目录下的sessions文件夹有什