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)时,可以定义一个通用的处理流程。
  • 代码复用:当多个类有相似的操作步骤,但具体实现不同,可以使用模板方法来复用代码,减少重复。
  • 控制算法的执行顺序:当你需要控制算法中某些步骤的执行顺序,而这些步骤的实现可能在子类中不同。
  • 框架设计:适用于设计框架,允许用户在特定的步骤中扩展或自定义行为,而不改变整体结构。
相关推荐
liang_jy2 分钟前
观察者模式
设计模式·面试
CodeWithMe3 分钟前
【C/C++】namespace + macro混用场景
c语言·开发语言·c++
SuperCandyXu1 小时前
leetcode2368. 受限条件下可到达节点的数目-medium
数据结构·c++·算法·leetcode
愈努力俞幸运2 小时前
c++ 头文件
开发语言·c++
~山有木兮2 小时前
C++设计模式 - 单例模式
c++·单例模式·设计模式
十五年专注C++开发2 小时前
CMake基础:gcc/g++编译选项详解
开发语言·c++·gcc·g++
周某某~3 小时前
四.抽象工厂模式
java·设计模式·抽象工厂模式
HUN金克斯3 小时前
C++/C函数
c语言·开发语言·c++
慢半拍iii3 小时前
数据结构——F/图
c语言·开发语言·数据结构·c++
iceslime3 小时前
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
数据结构·c++·算法·算法设计与分析