C++ 模板方法模式详解

模板方法模式(Template Method Pattern)是一种行为设计模式,它在父类中定义算法的框架 ,而将一些步骤的具体实现延迟到子类中,使得子类可以不改变算法结构的情况下重定义某些特定步骤。

核心概念

设计原则

模板方法模式遵循以下设计原则:

  1. 好莱坞原则:"不要调用我们,我们会调用你" - 父类控制流程,子类提供实现

  2. 开闭原则:对扩展开放(通过子类化),对修改关闭(不修改算法结构)

  3. 单一职责原则:将可变部分分离到不同方法中

主要优点

  1. 代码复用:将公共行为放在父类中

  2. 反向控制:父类控制流程,子类提供细节

  3. 灵活性:可以覆盖特定步骤而不改变结构

  4. 扩展性:容易添加新的具体实现

模式结构

主要组件

  1. AbstractClass(抽象类)

    • 定义模板方法和抽象的基本操作

    • 模板方法调用基本操作完成算法

  2. ConcreteClass(具体类)

    • 实现抽象类定义的基本操作

    • 可以覆盖某些默认实现

完整代码示例

复制代码
#include <iostream>
#include <memory>
#include <string>

// ==================== 抽象类 ====================
class DataProcessor {
protected:
    // 基本操作 - 由子类实现
    virtual void readData() = 0;
    virtual void processData() = 0;
    virtual void writeData() = 0;
    
    // 钩子方法 - 可选覆盖
    virtual bool shouldValidate() const { return true; }
    virtual void validateData() {
        std::cout << "默认数据验证..." << std::endl;
    }
    
    // 具体方法 - 公共实现
    void openConnection() {
        std::cout << "打开数据库连接..." << std::endl;
    }
    
    void closeConnection() {
        std::cout << "关闭数据库连接..." << std::endl;
    }
    
public:
    // 模板方法 - 定义算法框架
    void process() {
        openConnection();
        
        readData();
        
        if (shouldValidate()) {
            validateData();
        }
        
        processData();
        writeData();
        
        closeConnection();
    }
    
    virtual ~DataProcessor() = default;
};

// ==================== 具体类 ====================
class CsvDataProcessor : public DataProcessor {
protected:
    void readData() override {
        std::cout << "从CSV文件读取数据..." << std::endl;
    }
    
    void processData() override {
        std::cout << "处理CSV数据..." << std::endl;
    }
    
    void writeData() override {
        std::cout << "将处理结果写入CSV文件..." << std::endl;
    }
    
    bool shouldValidate() const override {
        return false; // CSV数据不需要验证
    }
};

class DatabaseDataProcessor : public DataProcessor {
protected:
    void readData() override {
        std::cout << "从数据库读取数据..." << std::endl;
    }
    
    void processData() override {
        std::cout << "处理数据库数据..." << std::endl;
    }
    
    void writeData() override {
        std::cout << "将处理结果写入数据库..." << std::endl;
    }
    
    void validateData() override {
        std::cout << "执行严格的数据验证..." << std::endl;
    }
};

class ApiDataProcessor : public DataProcessor {
protected:
    void readData() override {
        std::cout << "从API获取数据..." << std::endl;
    }
    
    void processData() override {
        std::cout << "处理API数据..." << std::endl;
    }
    
    void writeData() override {
        std::cout << "将处理结果通过API发送..." << std::endl;
    }
    
    bool shouldValidate() const override {
        return true;
    }
    
    void openConnection() { // 覆盖具体方法
        std::cout << "初始化API连接..." << std::endl;
    }
    
    void closeConnection() { // 覆盖具体方法
        std::cout << "终止API连接..." << std::endl;
    }
};

// ==================== 客户端代码 ====================
int main() {
    std::cout << "=== 模板方法模式演示: 数据处理流程 ===" << std::endl;
    
    std::cout << "\n处理CSV数据:" << std::endl;
    CsvDataProcessor csvProcessor;
    csvProcessor.process();
    
    std::cout << "\n处理数据库数据:" << std::endl;
    DatabaseDataProcessor dbProcessor;
    dbProcessor.process();
    
    std::cout << "\n处理API数据:" << std::endl;
    ApiDataProcessor apiProcessor;
    apiProcessor.process();
    
    return 0;
}

模式变体

1. 使用钩子方法

复制代码
class DocumentExporter {
protected:
    virtual void prepareData() = 0;
    virtual void generateFile() = 0;
    
    // 钩子方法 - 可选步骤
    virtual bool shouldCompress() const { return false; }
    virtual void compressFile() {
        std::cout << "使用默认压缩算法压缩文件..." << std::endl;
    }
    
public:
    void exportDocument() {
        prepareData();
        generateFile();
        
        if (shouldCompress()) {
            compressFile();
        }
    }
};

2. 模板方法与策略模式结合

复制代码
// 策略接口
class ValidationStrategy {
public:
    virtual void validate() = 0;
    virtual ~ValidationStrategy() = default;
};

// 模板方法抽象类
class ReportGenerator {
    std::unique_ptr<ValidationStrategy> validationStrategy_;
    
protected:
    virtual void fetchData() = 0;
    virtual void formatReport() = 0;
    
    void validateData() {
        if (validationStrategy_) {
            validationStrategy_->validate();
        }
    }
    
public:
    void setValidationStrategy(std::unique_ptr<ValidationStrategy> strategy) {
        validationStrategy_ = std::move(strategy);
    }
    
    void generate() {
        fetchData();
        validateData();
        formatReport();
    }
};

实际应用场景

  1. 框架设计:定义算法框架,允许用户自定义部分步骤

  2. 数据处理流程:如示例中的数据读取-处理-写入流程

  3. 游戏开发:游戏循环的固定流程

  4. 编译器:编译流程中的固定步骤

  5. 测试框架:测试用例的执行流程

相关推荐
智能直播15 分钟前
RK3528 V4L2 框架 UVC 接口自动获取 H.264 / MJPEG / YUYV 格式:从内核采集到硬解分发
java·网络·实时音视频·视频编解码·h.264
别动我齐刘海23 分钟前
Linux 系统调试学习2
linux·运维·c++·人工智能·学习·机器学习·机器人
171320330计算机毕设编程23 分钟前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
badhope36 分钟前
Spring AI Alibaba停更:Java程序员的信任,还能被辜负几次?
java·spring
const_qiu43 分钟前
第一章 1.1-1.2:基础模型调用与 TypeScript 入门 —— Java 开发者的视角
java·javascript·typescript
Wang's Blog1 小时前
Java 项目实战: 交友项目 - Dubbo 负载均衡策略与实战验证
java·dubbo·交友
SL_staff1 小时前
销售知识库7天落地实践:面向业务侧的零代码嵌入方案
java·开源·产品
GreatSQL社区1 小时前
主从复制SQL线程中断——字符集砸出的坑
java·数据库·算法
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 入门案例:服务提供者搭建总结
java·交友
hudd6681 小时前
JavaEE 初阶 - 多线程(进阶)
java·开发语言·java-ee