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)时,可以定义一个通用的处理流程。
  • 代码复用:当多个类有相似的操作步骤,但具体实现不同,可以使用模板方法来复用代码,减少重复。
  • 控制算法的执行顺序:当你需要控制算法中某些步骤的执行顺序,而这些步骤的实现可能在子类中不同。
  • 框架设计:适用于设计框架,允许用户在特定的步骤中扩展或自定义行为,而不改变整体结构。
相关推荐
刃神太酷啦14 分钟前
Redis 进阶核心:持久化 (RDB/AOF)、事务与主从复制全解析----《Hello Redis!》(5)
linux·c语言·数据库·c++·redis·缓存·bootstrap
喜欢吃燃面3 小时前
深入 C++ STL:从 unordered_set与unordered_map到底层哈希表的原理与实现
数据结构·c++·散列表
FlightYe4 小时前
音视频修炼之基础理论(五):AAC格式与解析
android·linux·c++·音视频·aac
ShineWinsu5 小时前
对于MySQL:数据库的操作的解析
linux·数据库·c++·mysql·面试·笔试·库的操作
云小逸5 小时前
C++ 第一阶段:对象、内存与生命周期
开发语言·c++
夜航海图5 小时前
S-57 数据解剖:把一个 ENC 文件拆给你看
c++
(Charon)5 小时前
【C++】网络缓冲区设计(三):Chain Buffer链式缓冲区、动态扩容与跨节点读写
服务器·c++
软行7 小时前
LeetCode 每日一题 3876. 构造奇偶一致的数组 II
c++·算法·leetcode
繁星蓝雨7 小时前
C++设计原理———重载(extern “C“的由来、顺序依赖、语义依赖、overload、名称修饰符、对象操作、运算符重载、新增运算符、枚举和布尔类型)
c语言·c++·extern c·overload·重载·语义依赖·顺序依赖
handler017 小时前
【Linux】虚拟地址空间解析
linux·运维·c++·线程·进程·虚拟地址空间·虚拟地址