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

设计模式——模板模式

定义与基本概念

  • 模板模式(Template Pattern)是一种行为设计模式。它在一个抽象类中定义了一个操作的算法骨架,将一些步骤的实现延迟到具体子类中。这个抽象类就像是一个模板,定义了执行某个流程的基本框架,而具体的细节可以由不同的子类根据自身的需求来填充。
  • 例如,在制作饮品的过程中,制作饮品的流程(如准备材料、混合材料、添加调料、包装等)可以看作是一个模板。不同的饮品(如咖啡、茶)在这个流程的某些具体步骤(如混合材料、添加调料)上会有不同的做法,但整体的流程框架是相似的。

结构组成

  • 抽象模板(Abstract Template)类:
    它定义了一个或多个抽象方法,这些方法代表了算法中的某些步骤,其具体实现将由具体子类完成。同时,抽象模板类还定义了一个模板方法(Template Method),这个方法规定了算法的骨架,它按照一定的顺序调用其他方法(包括抽象方法和具体方法)。以饮品制作的例子来说,抽象模板类可能定义了prepare()(抽象方法,准备材料)、mix()(抽象方法,混合材料)、addSeasoning()(抽象方法,添加调料)、package()(具体方法,包装)和makeDrink()(模板方法)。makeDrink()方法的实现可能是按照准备材料、混合材料、添加调料、包装的顺序调用其他方法。
  • 具体模板(Concrete Template)类:
    继承自抽象模板类,实现了抽象模板类中的抽象方法。每个具体模板类代表了一种具体的实现方式,根据不同的业务需求来填充抽象方法的具体内容。在饮品制作的例子中,Coffee类和Tea类是具体模板类,Coffee类的prepare()方法可能是准备咖啡豆和水,mix()方法可能是研磨咖啡豆后煮咖啡,addSeasoning()方法可能是加糖和奶;而Tea类的prepare()方法可能是准备茶叶和水,mix()方法可能是泡茶,addSeasoning()方法可能是加柠檬片。

工作原理

  • 客户端代码创建具体模板类的对象,然后调用抽象模板类中定义的模板方法。模板方法在执行过程中,会按照预先定义的顺序调用其他方法,其中抽象方法的具体实现由具体模板类提供。这样,不同的具体模板类就可以在遵循相同算法骨架的基础上,实现不同的具体行为。
  • 例如,在一个数据处理系统中,有一个抽象的数据处理模板类,它定义了loadData()(抽象方法)、processData()(抽象方法)、saveData()(具体方法)和execute()(模板方法)。execute()方法按照先loadData(),再processData(),最后saveData()的顺序调用其他方法。具体的数据处理子类(如TextDataProcessor和ImageDataProcessor)实现了loadData()和processData()方法,以适应不同类型数据的处理方式。当客户端代码调用TextDataProcessor对象的execute()方法时,就会按照TextDataProcessor类实现的loadData()和processData()方法以及DataProcessor类(抽象模板类)定义的saveData()方法来完成文本数据的处理流程。

代码示例

以下是一个简单的 C++ 模板模式示例,以文件处理为例。

  • 首先是抽象模板类:
class FileHandler {
public:
    void processFile() {
        openFile();
        readFile();
        processContents();
        closeFile();
    }
    virtual void openFile() = 0;
    virtual void readFile() = 0;
    virtual void processContents() = 0;
    void closeFile() {
        std::cout << "文件已关闭。" << std::endl;
    }
};
  • 然后是具体模板类,以文本文件处理为例:
class TextFileHandler : public FileHandler {
public:
    void openFile() override {
        std::cout << "打开文本文件。" << std::endl;
    }
    void readFile() override {
        std::cout << "读取文本文件内容。" << std::endl;
    }
    void processContents() override {
        std::cout << "处理文本文件内容。" << std::endl;
    }
};
  • 另一个具体模板类,以二进制文件处理为例:
class BinaryFileHandler : public FileHandler {
public:
    void openFile() override {
        std::cout << "打开二进制文件。" << std::endl;
    }
    void readFile() override {
        std::cout << "读取二进制文件内容。" << std::endl;
    }
    void processContents() override {
        std::cout << "处理二进制文件内容。" << std::endl;
    }
};
  • 使用示例:
int main() {
    TextFileHandler textHandler;
    textHandler.processFile();
    std::cout << "------------------------" << std::endl;
    BinaryFileHandler binaryHandler;
    binaryHandler.processFile();
    return 0;
}

优点

  • 代码复用性高:
    抽象模板类定义的算法骨架可以被多个具体子类复用。在上述文件处理的例子中,processFile()方法的流程(打开文件、读取文件、处理内容、关闭文件)在文本文件处理和二进制文件处理中都可以使用,减少了代码的重复编写。
  • 可维护性好:
    由于算法的骨架和具体步骤的实现分离,当需要修改算法的整体流程时,只需要在抽象模板类中修改模板方法;当需要修改某个具体步骤的实现时,只需要在相应的具体子类中进行修改。例如,在一个软件系统的用户注册流程中,如果需要修改注册的整体流程(如增加验证步骤),可以在抽象的注册模板类中修改模板方法;如果需要修改某个验证方式(如密码验证),可以在具体的注册子类中修改相应的抽象方法的实现。
  • 符合开闭原则:
    可以很容易地通过创建新的具体子类来扩展系统的功能,而不需要修改已有的代码。比如,在文件处理系统中,如果要增加一种新的文件类型(如 XML 文件)的处理,只需要创建一个新的XMLFileHandler类,实现抽象模板类中的抽象方法即可。

缺点

  • 可能导致类层次复杂:
    如果有多个抽象方法需要具体子类实现,并且具体子类的数量较多,会导致类层次结构变得复杂。例如,在一个复杂的工作流系统中,每个工作流步骤都可能有多个抽象方法需要具体子类实现,随着工作流类型的增加,类的数量和层次结构会变得难以管理。
  • 子类的灵活性有限:
    具体子类必须遵循抽象模板类定义的算法骨架,这在一定程度上限制了子类的灵活性。如果某个具体子类需要对算法骨架进行较大的修改,可能需要重新设计整个类结构,或者采用其他设计模式来解决。

http://www.kler.cn/a/408294.html

相关文章:

  • UI自动化测试中公认最佳的设计模式-POM
  • 论文阅读——Intrusion detection systems using longshort‑term memory (LSTM)
  • python代码制作数据集的测试和数据质量检测思路
  • 《FreeRTOS任务删除篇》
  • Robot | 用 RDK 做一个小型机器人(更新中)
  • 取电快充协议芯片,支持全协议、内部集成LDO支持从UART串口读取电压电流消息
  • (二)Sping Boot学习——Sping Boot注意事项
  • 【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决
  • 分布式数据库中间件可以用在哪些场景呢
  • 【Y20030006】基于php+mysql的课程学习网站的设计与实现(附源码 配置 文档)
  • w055基于web的服装生产管理的设计与实现
  • 【设计模式】如何用C++实现适配器模式
  • Odoo :免费且开源的农牧行业ERP管理系统
  • 什么是 C++ 中的类型别名和 using 声明?如何使用类型别名和 using 声明?
  • Ultiverse 和web3新玩法?AI和GameFi的结合是怎样
  • RT-DETR融合[ECCV 2018]RCAN中的RCAB模块及相关改进思路
  • 《C++智能合约与区块链底层交互全解析:构建坚实的去中心化应用桥梁》
  • 微知-lspci访问到指定的PCIe设备的几种方式?(lspci -s bus;lspci -d devices)
  • Leetcode 每日一题 15.三数之和
  • Spring Boot OA:构建企业级办公自动化平台
  • 深入解析 EasyExcel 组件原理与应用
  • 基于RFSOC实现LFMCW雷达测距测速
  • IP-Adapter 开源项目介绍
  • 小程序-基于java+SpringBoot+Vue的流浪动物救助小程序设计与实现
  • 开发工具 - VSCode 快捷键
  • [产品管理-105]:制造业 VS 创造业, 1->N VS 0->1, 一致性 VS 创新性