1 核心思想
模板方法模式:在父类中定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式通过将不变行为移动到父类,去除子类中的重复代码来体现它的优势。
模板方法提供了一个很好的代码复用平台。当不变的行为和可变的行为在方法的子类中混合在一起时,不变的行为就会在子类中重复出现。我们可以通过模板方法模式把这些行为搬到单一的地方,这样就可以帮助子类摆脱重复的不变行为的纠缠。
AbstractClass是抽象类,其实也就是一个抽象模板,定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。
ConcreteClass,实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
模板方法模式就是把各子类相同的操作放到父类中,在父类中定义好调用逻辑。将其不同的部分使用虚函数进行不同的实现。客户端使用基类指针指向派生类对象。
2 具体实现
//AbstractClass.h
#include<iostream>
class AbstractClass
{
public:
AbstractClass();
virtual ~AbstractClass();
virtual int OPerationA() = 0;
virtual int OPerationB() = 0;
int TemplateMethod();
};
//ConcreteClassA.h
#include "AbstractClass.h"
class ConcreteClassA : public AbstractClass
{
public:
ConcreteClassA();
virtual ~ConcreteClassA();
virtual int OPerationA();
virtual int OPerationB();
};
//ConcreteClassB.h
#include "AbstractClass.h"
class ConcreteClassB : public AbstractClass
{
public:
ConcreteClassB();
virtual ~ConcreteClassB();
virtual int OPerationA();
virtual int OPerationB();
};
//AbstractClass.cpp
#include "AbstractClass.h"
AbstractClass::AbstractClass(){
}
AbstractClass::~AbstractClass(){
}
int AbstractClass::TemplateMethod(){
std::cout << "算法执行顺序为:" << std::endl;
OPerationA();
OPerationB();
return 0;
}
//ConcreteClassA.cpp
#include "ConcreteClassA.h"
ConcreteClassA::ConcreteClassA(){
}
ConcreteClassA::~ConcreteClassA(){
}
int ConcreteClassA::OPerationA(){
std::cout << "子类A执行操作A" << std::endl;
return 0;
}
int ConcreteClassA::OPerationB(){
std::cout << "子类A执行操作B" << std::endl;
return 0;
}
//ConcreteClassB.cpp
#include "ConcreteClassB.h"
ConcreteClassB::ConcreteClassB(){
}
ConcreteClassB::~ConcreteClassB(){
}
int ConcreteClassB::OPerationA(){
std::cout << "子类B执行操作A" << std::endl;
return 0;
}
int ConcreteClassB::OPerationB(){
std::cout << "子类B执行操作B" << std::endl;
return 0;
}
//main.cpp
#include "AbstractClass.h"
#include "ConcreteClassA.h"
#include "ConcreteClassB.h"
int main()
{
AbstractClass* pClass = new ConcreteClassB;
pClass->TemplateMethod();
return 0;
}
ps:模板方法模式在面向对象编程中早就被大量使用。
3 模板方法模式和策略模式、工厂方法模式的关系
3.1 模板方法模式 vs 策略模式
首先来复习下策略模式,策略模式定义了一个算法家族,并让这些算法可以相互交换。正因为每个算法都被封装起来了,所以客户可以轻易地使用不同的算法。
意图不同:
策略模式是为了让算法可以相互交换,模板方法模式却是定义了算法的执行大纲,而把某些具体函数的实现放入了子类中。在模板方法模式中,算法的个别步骤有不同的实现细节,但算法的结构依然保持不变。
实现方式不同:
策略模式是通过组合实现的,让客户选择算法实现。模板方法模式是依靠继承实现的。策略模式更有弹性,模板方法模式对算法更有控制权,减少了代码的重复。
3.2 模板方法模式 vs 工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让类把实例化推迟到子类。
相同点:
都是把某些函数的实现推迟到子类;
不同点:
工厂方法模式只是把对象创建的工作推迟到了子类,模板方法模式可以把更多的函数实现推迟到子类,更关键的是模板方法模式定义好了算法的调用步骤,这是工厂方法模式不具备的。
工厂方法模式可以认为是模板方法模式的一个特例。