C++ 设计模式——模板方法模式

模板方法模式

模板方法模式

模板方法模式是一种行为设计模式,它定义了一个算法的骨架,而将一些步骤延迟到子类中。通过这种方式,模板方法允许子类在不改变算法结构的情况下重新定义算法的某些特定步骤。

引入"模板方法"设计模式的定义(实现意图):定义一个操作中的算法的骨架(稳定部分),而将一些步骤延迟到子类中去实现(父类中定义虚函数,让子类实现/重写这个虚函数)从而达到在整体稳定的情况下产生一些变化的目的。

逐步重构并引入模板方法模式

假设我们需要处理不同格式的数据(如 CSV 和 JSON)。最初的实现可能是重复的代码。逐步重构的过程如下:

初始实现

为每种数据格式编写独立的处理逻辑:

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

// CSV 数据处理
void processCSV() {
    std::cout << "Reading data from CSV file." << std::endl;
    std::cout << "Processing CSV data." << std::endl;
    std::cout << "Writing data to CSV file." << std::endl;
}

// JSON 数据处理
void processJSON() {
    std::cout << "Reading data from JSON file." << std::endl;
    std::cout << "Processing JSON data." << std::endl;
    std::cout << "Writing data to JSON file." << std::endl;
}

int main() {
    processCSV();
    processJSON();
    return 0;
}
提取共性并引入模板方法模式

识别出读取、处理和写入的共性步骤,并创建一个抽象类 DataProcessor,定义模板方法 process() 和虚函数:

cpp 复制代码
class DataProcessor {
public:
    void process() {
        readData();
        processData();
        writeData();
    }

protected:
    virtual void readData() = 0;
    virtual void processData() = 0;
    virtual void writeData() = 0;
};
实现具体类

为每种数据格式实现具体类,重写虚函数:

cpp 复制代码
class CSVDataProcessor : public DataProcessor {
private:
    void readData() override {
        std::cout << "Reading data from CSV file." << std::endl;
    }

    void processData() override {
        std::cout << "Processing CSV data." << std::endl;
    }

    void writeData() override {
        std::cout << "Writing data to CSV file." << std::endl;
    }
};

class JSONDataProcessor : public DataProcessor {
private:
    void readData() override {
        std::cout << "Reading data from JSON file." << std::endl;
    }

    void processData() override {
        std::cout << "Processing JSON data." << std::endl;
    }

    void writeData() override {
        std::cout << "Writing data to JSON file." << std::endl;
    }
};

完整代码示例

以下是完整的实现代码:

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

// 抽象类
class DataProcessor {
public:
    void process() {
        readData();
        processData();
        writeData();
    }

protected:
    virtual void readData() = 0;    // 读取数据
    virtual void processData() = 0; // 处理数据
    virtual void writeData() = 0;   // 写入数据
};

// 具体类:CSV 数据处理
class CSVDataProcessor : public DataProcessor {
private:
    void readData() override {
        std::cout << "Reading data from CSV file." << std::endl;
    }

    void processData() override {
        std::cout << "Processing CSV data." << std::endl;
    }

    void writeData() override {
        std::cout << "Writing data to CSV file." << std::endl;
    }
};

// 具体类:JSON 数据处理
class JSONDataProcessor : public DataProcessor {
private:
    void readData() override {
        std::cout << "Reading data from JSON file." << std::endl;
    }

    void processData() override {
        std::cout << "Processing JSON data." << std::endl;
    }

    void writeData() override {
        std::cout << "Writing data to JSON file." << std::endl;
    }
};

// 示例用法
int main() {
    DataProcessor* processor;

    // 处理 CSV 数据
    processor = new CSVDataProcessor();
    processor->process();
    delete processor;

    // 处理 JSON 数据
    processor = new JSONDataProcessor();
    processor->process();
    delete processor;

    return 0;
}

模板方法模式的 UML 图

模板方法模式的 UML 类图通常包含一个抽象类和多个具体类。以下是模板方法模式的 UML 图示例:

UML 图详细介绍
    • DataProcessor 是抽象类,定义了模板方法 process() 和三个虚函数。
    • CSVDataProcessorJSONDataProcessor 是具体类,分别实现了读取、处理和写入 CSV 和 JSON 数据的逻辑。
  • 继承关系

    • 继承关系通过带实线箭头表示,显示了 CSVDataProcessorJSONDataProcessor 继承自 DataProcessor
  • 方法可见性

    • +:表示公共方法,可以被外部访问,比如 process()
    • -:表示私有方法,只能在类内部访问,比如 readData()processData()writeData()
    • #:表示保护方法,子类可以访问,但外部无法访问。

模板方法模式适用于以下场景

  • 算法的框架:当你有一个算法的框架,但其中某些步骤需要在多个子类中实现时,模板方法模式非常适合。例如,处理不同格式的文件(如 CSV、XML、JSON)时,可以定义一个通用的处理流程。
  • 代码复用:当多个类有相似的操作步骤,但具体实现不同,可以使用模板方法来复用代码,减少重复。
  • 控制算法的执行顺序 :当你需要控制算法中某些步骤的执行顺序,而这些步骤的实现可能在子类中不同。
    个算法的框架,但其中某些步骤需要在多个子类中实现时,模板方法模式非常适合。例如,处理不同格式的文件(如 CSV、XML、JSON)时,可以定义一个通用的处理流程。
  • 代码复用:当多个类有相似的操作步骤,但具体实现不同,可以使用模板方法来复用代码,减少重复。
  • 控制算法的执行顺序:当你需要控制算法中某些步骤的执行顺序,而这些步骤的实现可能在子类中不同。
  • 框架设计:适用于设计框架,允许用户在特定的步骤中扩展或自定义行为,而不改变整体结构。
相关推荐
闻缺陷则喜何志丹9 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
charlie11451419120 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
小林熬夜学编程31 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
倔强的石头10642 分钟前
【C++指南】类和对象(九):内部类
开发语言·c++
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导2 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Ronin3053 小时前
11.vector的介绍及模拟实现
开发语言·c++
✿ ༺ ོIT技术༻3 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工3 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++