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

​【C++设计模式】第二十一篇:模板方法模式(Template Method)

注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

算法骨架的标准化定义


1. 模式定义与用途

核心思想

  • 模板方法模式:在父类中定义算法的骨架,将某些步骤延迟到子类实现,使得子类不改变算法结构即可重写特定步骤。
  • 关键用途
    ​1.代码复用:提取多个类的共同流程到父类。
    ​2.流程标准化:确保算法步骤的执行顺序不变。
    ​3.扩展性:子类仅需关注差异化的实现细节。

经典场景

  • 数据解析框架(固定解析流程,支持多种格式)。
  • 游戏角色行为(如攻击流程统一,子类实现不同攻击方式)。
  • 自动化测试框架(测试步骤固定,具体操作可定制)。

2. 模式结构解析

UML类图

+---------------------+       
|   AbstractClass     |      
+---------------------+        
| + templateMethod() |       
| + step1()           |     
| + step2()           |  
| + step3()           |  
+---------------------+  
          ^  
          |  
          |  
   +-----------------+  
   |   ConcreteClass |  
   +-----------------+  
   | + step2()       |  
   +-----------------+  

角色说明

  1. AbstractClass:抽象类,定义模板方法(算法骨架)和抽象步骤(step2())。
  2. ConcreteClass:具体子类,实现父类定义的抽象步骤。

3. 现代C++实现示例

场景:数据报告生成器

​步骤1:定义抽象模板类
#include <iostream>  
#include <memory>  

// 抽象报告生成器  
class ReportGenerator {  
public:  
    virtual ~ReportGenerator() = default;  

    // 模板方法(固定流程)  
    void generateReport() {  
        collectData();  
        processData();  // 抽象步骤  
        formatReport();  
        saveReport();  
    }  

protected:  
    // 通用步骤(已实现)  
    void collectData() {  
        std::cout << "收集数据...\n";  
    }  

    virtual void processData() = 0;  // 抽象步骤  

    void formatReport() {  
        std::cout << "格式化报告为PDF...\n";  
    }  

    void saveReport() {  
        std::cout << "保存报告到服务器\n";  
    }  
};  
步骤2:实现具体子类
// 销售报告生成器  
class SalesReport : public ReportGenerator {  
protected:  
    void processData() override {  
        std::cout << "处理销售数据:计算总销售额和增长率\n";  
    }  
};  

// 库存报告生成器  
class InventoryReport : public ReportGenerator {  
protected:  
    void processData() override {  
        std::cout << "处理库存数据:分析缺货商品和周转率\n";  
    }  

    // 扩展:重写非抽象步骤  
    void saveReport() {  
        std::cout << "保存报告到本地数据库\n";  
    }  
};  
步骤3:客户端代码
int main() {  
    SalesReport salesReport;  
    salesReport.generateReport();  
    /* 输出:  
        收集数据...  
        处理销售数据:计算总销售额和增长率  
        格式化报告为PDF...  
        保存报告到服务器  
    */  

    InventoryReport inventoryReport;  
    inventoryReport.generateReport();  
    /* 输出:  
        收集数据...  
        处理库存数据:分析缺货商品和周转率  
        格式化报告为PDF...  
        保存报告到本地数据库  
    */  
}  

4. 应用场景示例

场景1:游戏角色攻击流程

class Character {  
public:  
    void attack() {  
        aim();  
        loadWeapon();   // 抽象方法  
        fire();  
    }  

protected:  
    virtual void loadWeapon() = 0;  
    void aim() { std::cout << "瞄准目标\n"; }  
    void fire() { std::cout << "开火!\n"; }  
};  

class Sniper : public Character {  
protected:  
    void loadWeapon() override {  
        std::cout << "装填狙击步枪\n";  
    }  
};  

class Mage : public Character {  
protected:  
    void loadWeapon() override {  
        std::cout << "凝聚魔法能量\n";  
    }  
};  

场景2:跨平台文件解析器

class FileParser {  
public:  
    void parse(const std::string& path) {  
        openFile(path);  
        validateHeader();  // 抽象方法  
        extractContent();  
        closeFile();  
    }  

protected:  
    virtual void validateHeader() = 0;  
    void openFile(const std::string& path) { /* 通用实现 */ }  
    void extractContent() { /* 通用实现 */ }  
    void closeFile() { /* 通用实现 */ }  
};  

class XMLParser : public FileParser {  
protected:  
    void validateHeader() override {  
        std::cout << "验证XML头部...\n";  
    }  
};  

5. 优缺点分析

​优点​缺点
避免重复代码,提升复用性父类修改可能影响所有子类
确保核心流程不可变子类可能被迫实现无用的抽象方法
通过钩子方法(Hook)灵活扩展过度继承可能导致类层次复杂

6. 调试与优化策略

调试技巧(VS2022)​

1. ​跟踪模板方法执行流程:
  • generateReport()方法内设置断点,验证步骤顺序是否正确。
2. 验证子类方法覆盖:
  • 使用 ​重写指示符override 确保子类正确实现抽象方法。

性能优化

1. ​钩子方法(Hook)​:
  • 在父类中提供空实现的钩子方法,允许子类选择性扩展。
class ReportGenerator {  
protected:  
    virtual void preSaveHook() {}  // 钩子方法  
    void saveReport() {  
        preSaveHook();  
        std::cout << "保存报告到服务器\n";  
    }  
};  

class InventoryReport : public ReportGenerator {  
protected:  
    void preSaveHook() override {  
        std::cout << "压缩报告数据...\n";  
    }  
};  
2. ​模板方法拆分:
  • 将大型模板方法拆分为多个小方法,提升可维护性。

相关文章:

  • Docker命令笔记
  • 网页制作14-Javascipt时间特效の显示动态日期
  • HTB 学习笔记 【中/英】《Web 应用 - 布局》P2
  • JavaCV
  • java集合框架的List 接口提供了两种主要的访问元素的方式:迭代器(Iterator)和索引访问,优缺点对比
  • 《C++:无可替代的编程传奇》:此文为AI自动生成
  • elementui table 自动滚动 纯js实现
  • 【fNIRS可视化学习1】基于NIRS-SPM进行光极可视化并计算通道坐标
  • ubuntu系统下添加pycharm到快捷启动栏方法
  • 【漫话机器学习系列】134.基于半径的最近邻分类器(Radius-Based Nearest Neighbor Classifier)
  • TCP 三次握手四次挥手过程详解
  • 【C++重要!!!】赋值与初始化的区别
  • Flutter三棵树是什么,为什么这么设计
  • 【5*】坐标规则类动态规划学习笔记
  • MindGYM:一个用于增强视觉-语言模型推理能力的合成数据集框架,通过生成自挑战问题来提升模型的多跳推理能力。
  • 【SpringMVC】常用注解:@PathVariable
  • vue2自定义指令实现 el-input 输入数字,小数点两位 最高10位,不满足则截取符合规则的值作为新值
  • 【Pytorch实战教程】拆解PyTorch中的多头注意力:原来Transformer的核心组件可以这样玩
  • 关于WPS的Excel点击单元格打开别的文档的两种方法的探究【为单元格添加超链接】
  • 【VS小知识】VS如何保存UTF8
  • 外企聊营商|特雷通集团:税务服务“及时雨”
  • 4月份全国企业销售收入同比增长4.3%
  • 国台办:实现祖国完全统一是大势所趋、大义所在、民心所向
  • 阿坝州委书记徐芝文已任四川省政府党组成员
  • 中东睿评|特朗普中东三国行:喧嚣的形式与空洞的实质
  • 挖掘机4月销量同比增17.6%,出口增幅创近两年新高