1、概念定义
-
定义一个操作中的算法的骨架结构(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的骨架结构即可重定义(override重写)该算法的某些特定步骤
-
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但是各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现
-
如何在确定稳定操作结构的前提下,来罗应对各种各个子步骤的变化或者晚期实现需求?
2、Demo举例
-
例如现在存在两个开发人员,一个开发人员负责编写Library库(底层开发),另外一个开发人员编写Application(高层开发)。
-
最后将Library和Application组合完成一个算法的结构骨架
2.1、结构化软件设计流程
- Library中提供step1、step3、step5三个方法
- Application中提供step2、step4两个方法
- run()一个算法骨架结构,也需要Application人员编写
- 看起来这个代码很好是一段低耦合的代码,实际上这里存在问题的。
- step1、step3、step5方法完全暴露给了高层开发人员,其他高层开发者也能调用到
- run算法骨架结构实际来说是一个稳定的东西,就这种执行流程,变化主要是在step2、step4中
- 这是一种结构化软件设计流程,是一种早绑定的例子
class Library{
public:
void step1(){ }
void step3(){ }
void step5(){ }
virtual ~Library(){ }
};
class Application{
public:
bool step2(){ }
void step4(){ }
virtual ~Application(){ }
};
void run()
{
Library lib;
Application app;
lib.step1();
if(app.step2()){
lib.step3();
}
for(int i = 0;i < 4;i++){
app.step4();
}
lib.step5();
}
2.2、面向对象软件设计流程
- 首先需要清楚一点:run方法是稳定的(稳定这个词是相对的),这个算法骨架结构的变化没有step2、step4的变化结构快
- 通过纯虚函数表明Library是一个抽象类,而如果想使用这个抽象类只需要继承然后实现抽象方法即可
- protected将方法隐藏不对外public暴露给无关调用者,只允许子类调用
- 只对外暴露算法骨架结构的调用入口,至于整个执行流程是怎么样的无须Application应用层(高层开发者)关心
- 子类只需要继承实现step2、step4方法,使用时只需要使用多态的动态绑定(晚绑定)来实现
- 这里主要使用了多态的机制,将高层开发者对Library的使用机制释放出来
- 这种晚绑定主要是通过多态的动态绑定来实现,动态绑定的本质也是一个回调函数的指针
class Library{
public:
// 稳定template method
void run(){
step1();
if(step2()){ // 支持变化 --> 虚函数的多态调用
step3();
}
for(int i = 0;i < 4;i++){
step4(); // 支持变化 --> 虚函数的多态调用
}
step5();
}
virtual ~Library(){
}
protected:
void step1(){ // 稳定 }
void step3(){ // 稳定 }
void step5(){ // 稳定 }
virtual bool step2() = 0; // 变化
virtual void step4() = 0; // 变化
};
class Application: public Library{
protected:
virtual bool step2() override {
// 子类重写实现
}
virtual void step4() override {
// 子类重写实现
}
};
int main()
{
Library *library = new Application();
library->run();
return 0;
}
3、总结
- Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它应用最简洁的机制(虚函数的多态性)为很多引用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构
- 除了可以灵活对应子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用
- 在具体实现方面,被Template Method调用的虚函数方法可以有实现也可以没有任何实现(纯虚函数),但是一般将它们设置为protected方法