当前位置: 首页 > news >正文

模板方法模式C++

模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,将某些步骤延迟到子类中实现。这种模式让子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤,从而实现代码复用和扩展。

模板方法模式的核心角色

  1. AbstractClass(抽象类):定义算法的骨架(模板方法),包含多个抽象方法(步骤)和可能的钩子方法
  2. ConcreteClass(具体子类):实现抽象类中的抽象方法,完成算法中特定于子类的步骤

C++实现示例

以下以"饮料制作流程"为例实现模板方法模式,冲泡咖啡和泡茶的流程相似(都需要煮水、冲泡、倒杯、加调料),但具体步骤存在差异:

#include <iostream>
#include <string>// 抽象类:饮料
class Beverage {
public:// 模板方法:定义算法骨架,声明为final防止子类重写void prepareRecipe() final {boilWater();    // 步骤1:煮水brew();         // 步骤2:冲泡(抽象方法,子类实现)pourInCup();    // 步骤3:倒杯if (customerWantsCondiments()) {  // 钩子方法:判断是否需要加调料addCondiments();  // 步骤4:加调料(抽象方法,子类实现)}}// 抽象方法:冲泡(子类实现)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;}// 重写钩子方法:默认不加调料bool customerWantsCondiments() override {return false;  // 茶默认不加柠檬}
};// 客户端代码
void makeBeverage(Beverage* beverage) {std::cout << "\n开始制作饮料..." << std::endl;beverage->prepareRecipe();std::cout << "饮料制作完成" << std::endl;
}int main() {// 制作咖啡Beverage* coffee = new Coffee();makeBeverage(coffee);// 制作茶Beverage* tea = new Tea();makeBeverage(tea);// 清理资源delete coffee;delete tea;return 0;
}

代码解析

  1. 模板方法(prepareRecipe

    • 定义了饮料制作的固定流程(煮水→冲泡→倒杯→加调料),用final修饰防止子类修改算法结构
    • 其中boilWaterpourInCup是通用步骤(具体方法),brewaddCondiments是抽象步骤(由子类实现)
  2. 抽象方法(brewaddCondiments

    • 声明为纯虚函数,强制子类实现,这些步骤是算法中因具体类型而异的部分
    • 咖啡实现为"冲泡咖啡粉"和"加糖牛奶",茶实现为"浸泡茶叶"和"加柠檬"
  3. 钩子方法(customerWantsCondiments

    • 提供默认实现(返回true),子类可根据需要重写
    • 咖啡重写为询问用户是否加调料,茶重写为默认不加调料,增强了算法的灵活性
  4. 子类扩展

    • 子类通过实现抽象方法定制特定步骤,无需修改算法整体结构
    • 钩子方法允许子类有选择地参与算法,而非强制实现所有步骤

模板方法模式的优缺点

优点

  • 封装不变部分,扩展可变部分,实现代码复用(通用步骤在父类实现)
  • 子类专注于实现特定步骤,无需关心算法整体结构
  • 通过钩子方法提供灵活的扩展点,增强了适应性
  • 符合开放-封闭原则(扩展新子类无需修改父类)

缺点

  • 父类中的抽象方法过多时,会导致子类实现负担加重
  • 算法骨架被固定在父类,如需修改整体流程需修改父类,违反开放-封闭原则
  • 可能增加系统复杂度(引入多个子类)

适用场景

  • 当多个子类存在公共行为(算法步骤),且这些行为的结构相同但细节不同时
  • 当需要控制子类扩展时(通过钩子方法限制扩展范围)
  • 当希望在不改变算法结构的前提下,允许子类定制某些步骤时

常见应用:

  • 框架中的生命周期方法(如Servlet的init()service()destroy()
  • 工具类中的算法模板(如排序算法的骨架,具体比较逻辑由子类实现)
  • 测试框架中的测试用例模板(固定测试流程,具体测试步骤由子类实现)

模板方法模式与策略模式的区别:模板方法通过继承实现算法步骤的定制,强调"继承式扩展";策略模式通过组合实现算法的替换,强调"组合式扩展"。

http://www.dtcms.com/a/332677.html

相关文章:

  • 基于 Spring AI + Ollama + MCP Client 打造纯本地化大模型应用
  • Java研学-SpringCloud(三)
  • 如何安装 Homestead ?
  • 【学习笔记】JVM内存模型
  • 告别碎片化管理!飞算JavaAI实现端到端业务全流程智能监控
  • Ubuntu DNS 综合配置与排查指南
  • IP生意的天花板更高了吗?
  • 【数据分享】2022 年黑龙江省小麦、玉米和水稻幼苗影像数据集
  • Logstash 实战指南:从入门到生产级日志处理
  • GitHub 热榜项目 - 日榜(2025-08-15)
  • 硬核实用!R+贝叶斯解决真实问题:参数估计(含可靠性分析) + 回归建模(含贝叶斯因子比较) + 生产级计算实践 赠「常见报错解决方案」秘籍!
  • ubuntu 24.04 通过部署ollama提供大模型api接口
  • 线程P5 | 单例模式[线程安全版]~懒汉 + 饿汉
  • CANDB++中的CAN_DBC快速编辑方法,使用文本编辑器(如notepad++和VScode)
  • Redis 知识点与应用场景
  • 六十六、【Linux数据库】MySQL数据导入导出 、 管理表记录 、 匹配条件
  • 日本服务器哪些服务商是可以免费试用的?
  • 拒绝“效果图”返工:我用Substance 3D Stager构建产品可视化工作流
  • 计算机视觉(opencv)实战五——图像平滑处理(均值滤波、方框滤波、高斯滤波、中值滤波)附加:视频逐帧平滑处理
  • vue2生命周期详解
  • Claude Opus 4.1深度解析:抢先GPT5发布,AI编程之王主动出击?
  • 【线上问题】1分钟学会如何定位 Java 应用 CPU 飙升问题
  • Spring中存在两个相同的Bean是否会报错?
  • Amazon Bedrock如何轻松实现复杂的生成式AI模型?
  • 纯C++实现halcon的threshold
  • 【Java EE进阶 --- SpringBoot】初识Spring(创建SpringBoot项目)
  • zynq代办事项
  • Vue 侦听器(watch 与 watchEffect)全解析2
  • 【100页PPT】数字化转型集团信息化总体解决方案(附下载方式)
  • Swift 实战:用最长递增子序列算法解“俄罗斯套娃信封”问题(LeetCode 354)