问题
在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的。Template提供了这种情况的一个实现框架。
Template模式是采用继承的方式实现这一点:将逻辑(算法)框架放在抽象基类中,并定义好细节的接口,子类中实现细节。
template模版模式:
很多资料也称TemplateMethod(模板方法模式)。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 抽象类:定义了一个模板方法,其中包含执行的步骤。还有固定方法和抽象方法
- 具体类:实现抽象方法具体行为
Template模式实际上就是利用面向对象中多态的概念实现算法实现细节和高层接口的松耦合。可以看到Template模式采取的是继承方式实现这一点的,由于继承是一种强约束性的条件,因此也给Template模式带来一些许多不方便的地方。
- 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
- 何时使用:有一些通用的方法。
- 如何解决:将这些通用算法抽象出来。
- 关键代码:在抽象类实现,其他步骤在子类实现。
- 应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。
- 优点: 1、封装不变部分,扩展可变部分。2、提取公共代码,便于维护。3、行为由父类控制,子类实现。
- 缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
- 使用场景: 1、有多个子类共有的方法,且逻辑相同。2、重要的、复杂的方法,可以考虑作为模板方法
小demo
TemplateMethod.h
// 抽象基类,定义算法的轮廓
class AbstractClass
{
public:
AbstractClass(){}
virtual ~AbstractClass(){}
// 这个函数中定义了算法的轮廓
void TemplateMethod();
protected:
// 纯虚函数,由派生类实现之
virtual void PrimitiveOperation1() = 0;
virtual void PrimitiveOperation2() = 0;
};
// 继承自AbstractClass,实现算法
class ConcreateClassA : public AbstractClass
{
public:
ConcreateClassA(){}
virtual ~ConcreateClassA(){}
protected:
virtual void PrimitiveOperation1();
virtual void PrimitiveOperation2();
};
// 继承自AbstractClass,实现算法
class ConcreateClassB : public AbstractClass
{
public:
ConcreateClassB(){}
virtual ~ConcreateClassB(){}
protected:
virtual void PrimitiveOperation1();
virtual void PrimitiveOperation2();
};
TemplateMethod.cpp
#include "TemplateMethod.h"
#include <iostream>
void AbstractClass::TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
}
void ConcreateClassA::PrimitiveOperation1()
{
std::cout << "PrimitiveOperation1 by ConcreateClassA\n";
}
void ConcreateClassA::PrimitiveOperation2()
{
std::cout << "PrimitiveOperation2 by ConcreateClassA\n";
}
void ConcreateClassB::PrimitiveOperation1()
{
std::cout << "PrimitiveOperation1 by ConcreateClassB\n";
}
void ConcreateClassB::PrimitiveOperation2()
{
std::cout << "PrimitiveOperation2 by ConcreateClassB\n";
}
main.cpp
#include "TemplateMethod.h"
#include <stdlib.h>
int main()
{
AbstractClass* pConcreateClassA = new ConcreateClassA();
AbstractClass* pConcreateClassB = new ConcreateClassB();
pConcreateClassA->TemplateMethod();
pConcreateClassB->TemplateMethod();
delete pConcreateClassA;
delete pConcreateClassB;
system("pause");
return 0;
}
Template模式是很简单模式,但是也应用很广的模式。Template是采用继承的方式实现算法的异构,其关键点就是将通用算法封装在抽象基类中,并将不同的算法细节放到子类中实现。Template模式获得一种反向控制结构效果,这也是面向对象系统的分析和设计中一个原则DIP(依赖倒置:Dependency Inversion Principles)。其含义就是父类调用子类的操作(高层模块调用低层模块的操作),低层模块实现高层模块声明的接口。这样控制权在父类(高层模块),低层模块反而要依赖高层模块。
与其他模式的关系
- 工厂方法模式是模板方法模式的一种特殊形式。 同时, 工厂方法可以作为一个大型模板方法中的一个步骤。
- 模板方法基于继承机制: 它允许你通过扩展子类中的部分内容来改变部分算法。 策略模式基于组合机制:通过对相应行为提供不同的策略来改变对象的部分行为。 模板方法在类层次上运作, 因此它是静态的。 策略在对象层次上运作, 因此允许在运行时切换行为。