C++模板方法模式
·
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。这种模式使得子类可以在不改变算法结构的情况下,重新定义算法中的某些特定步骤。
模板方法模式的核心角色
- 抽象类(Abstract Class):定义算法的骨架(模板方法),并声明一些抽象的primitive方法供子类实现
- 具体子类(Concrete Class):实现抽象类中声明的primitive方法,完成算法中与具体子类相关的步骤
模板方法模式的实现示例
下面以"饮料制作流程"为例展示模板方法模式的实现,冲泡咖啡和泡茶的流程相似但某些步骤不同,我们可以用模板方法定义通用流程:
#include <iostream>
#include <string>
// 抽象类:饮料
class Beverage {
public:
// 模板方法:定义算法骨架,声明为final防止子类重写
void prepareRecipe() final {
boilWater(); // 煮沸水
brew(); // 冲泡(子类实现)
pourInCup(); // 倒入杯子
if (customerWantsCondiments()) { // 钩子方法:是否加调料
addCondiments(); // 添加调料(子类实现)
}
}
// 抽象方法:冲泡
virtual void brew() = 0;
// 抽象方法:添加调料
virtual void addCondiments() = 0;
// 具体方法:煮沸水(所有饮料通用)
void boilWater() {
std::cout << "煮沸水" << std::endl;
}
// 具体方法:倒入杯子(所有饮料通用)
void pourInCup() {
std::cout << "倒入杯子中" << std::endl;
}
// 钩子方法:默认返回true,表示加调料
virtual bool customerWantsCondiments() {
return true;
}
virtual ~Beverage() = default;
};
// 具体子类:咖啡
class Coffee : public Beverage {
public:
void brew() override {
std::cout << "用沸水冲泡咖啡粉" << std::endl;
}
void addCondiments() override {
std::cout << "添加糖和牛奶" << std::endl;
}
// 重写钩子方法:询问用户是否需要调料
bool customerWantsCondiments() override {
std::string answer;
std::cout << "请问需要为您的咖啡添加糖和牛奶吗?(y/n) ";
std::cin >> answer;
return answer == "y" || answer == "Y";
}
};
// 具体子类:茶
class Tea : public Beverage {
public:
void brew() override {
std::cout << "用沸水浸泡茶叶" << std::endl;
}
void addCondiments() override {
std::cout << "添加柠檬" << std::endl;
}
// 可以选择不重写钩子方法,使用父类默认实现
};
// 客户端使用
int main() {
std::cout << "=== 制作咖啡 ===" << std::endl;
Beverage* coffee = new Coffee();
coffee->prepareRecipe();
std::cout << "\n=== 制作茶 ===" << std::endl;
Beverage* tea = new Tea();
tea->prepareRecipe();
// 清理资源
delete coffee;
delete tea;
return 0;
}
模板方法模式的核心概念
- 模板方法(Template Method):定义算法的骨架,通常声明为
final防止子类重写 - Primitive方法:抽象方法,由子类实现,是算法中的可变步骤
- 具体方法(Concrete Method):在抽象类中实现,是算法中的固定步骤
- 钩子方法(Hook Method):在抽象类中提供默认实现(通常为空),子类可以选择性重写,用于控制算法流程
模板方法模式的工作原理
- 抽象类定义算法的整体框架(模板方法)
- 模板方法按顺序调用一系列方法,包括具体方法、抽象方法和钩子方法
- 具体方法在抽象类中实现,提供所有子类都需要的共同功能
- 抽象方法由子类实现,提供特定于子类的功能
- 钩子方法可以被子类重写,用于改变算法的流程或行为
模板方法模式与策略模式的区别
- 模板方法模式:通过继承实现算法的变化,算法骨架固定,步骤实现可变
- 策略模式:通过组合实现算法的变化,整个算法可以被替换
模板方法模式的应用场景
- 多个子类有公共的方法,且逻辑基本相同时
- 需要固定算法骨架,只允许改变其中某些步骤时
- 需要控制子类扩展的场景(钩子方法可以限制扩展)
- 框架设计中,用于定义扩展点(如框架中的生命周期方法)
模板方法模式的优缺点
优点:
- 封装了不变部分,扩展了可变部分,符合开放-封闭原则
- 提取了公共代码,减少了代码冗余
- 子类只需要实现自己关心的步骤,简化了子类的实现
- 控制了算法的整体结构,确保了算法的一致性
缺点:
- 模板方法引入了反向控制结构,子类执行的结果影响父类,增加了代码理解难度
- 如果算法骨架需要修改,必须修改抽象类,可能影响所有子类
- 可能导致类数量增加,每个不同的实现都需要一个子类
模板方法模式在C++的许多框架中都有广泛应用,例如MFC中的CWnd类体系,定义了窗口的生命周期模板方法;STL中的迭代器模式也间接使用了模板方法的思想。在框架设计中,模板方法模式是一种常用的设计手段,用于定义框架的骨架和扩展点。
更多推荐

所有评论(0)