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

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【设计模式大纲】


【简介】

        --什么是模板方法模式(第18种设计模式)

        模板方法模式(Template Method Pattern)是⼀种行为型设计模式, 它定义了⼀个算法的骨架,将⼀些步骤的实现延迟到⼦类。模板方法模式使得⼦类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

        举个简单的例⼦,做⼀道菜通常都需要包含⾄少三步:

  • 准备⻝材
  • 亨饪过程
  • 上菜

        不同菜品的亨饪过程是不⼀样的,但是我们可以先定义⼀个”⻣架”,包含这三个步骤,亨饪过程的过程放到具体的炒菜类中去实现,这样,⽆论炒什么菜,都可以沿⽤相同的炒菜算法,只需在⼦类中实现具体的炒菜步骤,从而提⾼了代码的复⽤性。


【基本结构】

        模板⽅法模式的基本结构包含以下两个角色:

  • 模板类AbstractClass :由⼀个模板⽅法和若⼲个基本⽅法构成,模板⽅法定义了逻辑的⻣架,按照顺序调⽤包含的基本⽅法,基本⽅法通常是⼀些抽象⽅法,这些⽅法由⼦类去实现。基本⽅法还包含⼀些具体⽅法,它们是算法的⼀部分但已经有默认实现,在具体⼦类中可以继承或者重写。
  • 具体类ConcreteClass :继承⾃模板类,实现了在模板类中定义的抽象⽅法,以完成算法中特定步骤的具体实现。

【简易实现】

        模板⽅法模式的简单示例如下:先以Java代码作以说明

1. 定义模板类,包含模板⽅法,定义了算法的⻣架, ⼀般都加上final 关键字C++为 const关键字),避免子类重写。

// 模板类
abstract class AbstractClass {
    // 模板⽅法,定义了算法的⻣架
    public final void templateMethod() {
        step1();
        step2();
        step3();
    }
    // 抽象⽅法,由⼦类实现
    protected abstract void step1();
    protected abstract void step2();
    protected abstract void step3();
}

2. 定义具体类, 实现模板类中的抽象⽅法

// 具体类
class ConcreteClass extends AbstractClass {
    @Override
    protected void step1() {
        System.out.println("Step 1 ");
    }
    @Override
    protected void step2() {
        System.out.println("Step 2 ");
    }
    @Override
    protected void step3() {
        System.out.println("Step 3");
    }
}

3. 客户端实现

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/

public class Main {
    public static void main(String[] args) {
        AbstractClass concreteTemplate = new ConcreteClass();
        // 触发整个算法的执⾏
        concreteTemplate.templateMethod();
    }
}

【应用场景】

        模板⽅法模式将算法的不变部分被封装在模板⽅法中,而可变部分算法由⼦类继承实现,这样做可以很好的提⾼代码的复⽤性,但是当算法的框架发⽣变化时,可能需要修改模板类,这也会影响到所有的⼦类。
        总体来说,当算法的整体步骤很固定,但是个别步骤在更详细的层次上的实现可能不同时,通常考虑模板⽅法模式来处理。在已有的⼯具和库中, Spring框架中的JdbcTemplate 类使⽤了模板⽅法模式,其中定义了⼀些执⾏数据库操作的模板⽅法,具体的数据库操作由回调函数提供。⽽在Java的JDK源码中, AbstractList 类也使⽤了模板⽅法模式,它提供了⼀些通用的⽅法,其中包括⼀些模板⽅法。具体的列表操作由⼦类实现。


【C++编码部分】

1. 题目描述

        小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。

        咖啡制作过程包括以下步骤:

        1. 研磨咖啡豆 Grinding coffee beans

        2. 冲泡咖啡 Brewing coffee

        3. 添加调料 Adding condiments

        其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk。

2. 输入描述

        多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。

3. 输出描述

        根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。

4. C++编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// 前置声明

// 抽象模板类 -- 包含模板⽅法,定义了算法的⻣架, ⼀般都加上final 关键字,避免⼦类重写
class CoffeeMaker;
// 实现具体类 -- 美式
class AmericanCoffeeMaker;
// 实现具体类 -- 拿铁
class LatteCoffeeMaker;

// 类的定义

// 抽象模板类
class CoffeeMaker
{
// 成员接口函数
public:
    // 框架接口函数
    const void TemplateCoffeeMethod(){
        // 步骤一
        GrindingCoffeeBeans();
        // 步骤二
        BrewingCoffee();
        // 步骤三
        AddingCondiments();
        // 空行
        std::cout << endl;
    }
    // 研磨咖啡豆工序
    virtual void GrindingCoffeeBeans() = 0;
    // 冲泡咖啡工序
    virtual void BrewingCoffee() = 0;
    // 添加调料工序
    virtual void AddingCondiments(){
        std::cout << "Adding condiments" << endl;
    }
};

// 实现具体类 -- 美式
class AmericanCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
    string _coffeeName;

// 成员接口函数重载
public:
    // 构造函数
    AmericanCoffeeMaker(string name){
        this->_coffeeName = name;
        std::cout<< "Making " << _coffeeName << ":"<<endl;
    }
    // 研磨咖啡豆工序 重载
    void GrindingCoffeeBeans() override {
        std::cout << "Grinding coffee beans" << endl;
    }
    // 冲泡咖啡工序 重载
    void BrewingCoffee() override {
        std::cout << "Brewing coffee" << endl;
    }
};

// 实现具体类 -- 拿铁
class LatteCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
    string _coffeeName;

// 成员接口函数重载
public:
    // 构造函数
    LatteCoffeeMaker(string name){
        this->_coffeeName = name;
        std::cout<< "Making " << _coffeeName << ":"<<endl;
    }
    // 研磨咖啡豆工序 重载
    void GrindingCoffeeBeans() override {
        std::cout << "Grinding coffee beans" << endl;
    }
    // 冲泡咖啡工序 重载
    void BrewingCoffee() override {
        std::cout << "Brewing coffee" << endl;
    }
    // 添加调料工序 重载
    void AddingCondiments() override {
        std::cout << "Adding milk" << endl;
        std::cout << "Adding condiments" << endl;
    }
};


// 客户端代码
int main()
{
    // 输入的咖啡制作类型
    int type = 0;
    // 构造抽象模板类
    CoffeeMaker *coffee = nullptr;
    while(std::cin >> type){
        if(type == 1){
            coffee = new AmericanCoffeeMaker("American Coffee");
        }
        else if(type == 2){
            coffee = new LatteCoffeeMaker("Latte");
        }
        else break;
        
        // 开始统一制作咖啡
        coffee->TemplateCoffeeMethod();
    }
    
    // 析构
    if(coffee != nullptr){
        delete coffee;
        coffee = nullptr;
    }
    
    return 0;
}



......

To be continued.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/335914.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Linux高性能服务器编程》笔记02

Linux高性能服务器编程 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第06章 高级I/O函数6.1 pipe函数6.2 dup函数和dup2函数6.3 readv 函数和writev 函数6.4 sendfile 函数6.…

基于SSM的KTV包厢管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于SSM的KTV包厢管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过…

软件测试|sqlalchemy一对一关系详解

简介 SQLAlchemy 是一个强大的 Python ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它允许我们将数据库表映射到 Python 对象&#xff0c;并提供了丰富的关系模型来处理不同类型的关系&#xff0c;包括一对一关系。在本文中&#xff0c;我们将深入探讨 SQLAlchemy …

后台管理系统: 数据可视化基础

数据可视化简单理解&#xff0c;就是将数据转换成易于人员辨识和理解的视觉表现形式&#xff0c;如各种 2D 图表、3D 图表、地图、矢量图等等。 例如Excel等等 canvas <canvas> 标签只是图形容器&#xff0c;相当于一个画布&#xff0c;canvas 元素本身是没有绘图能力…

算法常用思路总结

思路 1. 求数组中最大最小值思路代码 2. 计算阶乘思路&#xff1a;代码&#xff1a; 3. 得到数字的每一位思路代码 4. 计算时间类型5. 最大公约数、最小公倍数6. 循环数组的思想题目&#xff1a;猴子选大王代码 补充经典例题1. 复试四则运算题目内容题解 2. 数列求和题目内容题…

安防监控系统EasyCVR平台用户调用设备参数,信息不返回是什么原因?

安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;平台能在复杂的网络环境中&#xff08;专网、局域网、广域网、VPN、公网等&#xff09;将前端海量的设备进行统一集中接入与视频汇聚管理&#xff0c;平台支持设备通过4G、5G、WIFI、有…

限流算法之流量控制的平滑之道:滑动时间窗算法

文章目录 引言简介优点缺点样例样例图样例代码 应用场景结论 引言 在互联网应用中&#xff0c;流量控制是一个重要的组件&#xff0c;用于防止系统过载和保护核心资源。常见的限流算法包括固定窗口算法和滑动时间窗算法。本文将重点介绍滑动时间窗算法&#xff0c;并分析其优缺…

掌握虚拟化:PVE平台安装教程与技术解析

&#x1f31f;&#x1f30c; 欢迎来到知识与创意的殿堂 — 远见阁小民的世界&#xff01;&#x1f680; &#x1f31f;&#x1f9ed; 在这里&#xff0c;我们一起探索技术的奥秘&#xff0c;一起在知识的海洋中遨游。 &#x1f31f;&#x1f9ed; 在这里&#xff0c;每个错误都…

Windows系统下使用docker-compose安装mysql8和mysql5.7

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7 文章目录 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7MySQL81.新建文件夹2.创建…

结构体的使用和结构体指针的定义注意事项

1、使用背景 由于想把不同地方的三个变量数据存放在一个结构体中&#xff0c;并且调用W25QXX_Write((u8*)p,FLASH_SIZE-100,SIZE); //从倒数第100个地址处开始,写入SIZE长度的数据。调用flash写数据函数&#xff0c;其参数为指针地址&#xff0c;于是需要定义一个结构体和指向结…

最小二乘法拟合二维点

方法1&#xff1a;使用np.polyfit()函数进行拟合 import numpy as np import matplotlib.pyplot as plt# 模拟数据 x np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) y np.array([1, 3, 2, 4, 7, 10, 11, 15, 17, 20])# 使用多项式拟合&#xff0c;这里选择二次多项式 coefficie…

C++——函数的定义

1&#xff0c;概述 作用&#xff1a;将一段经常使用的代码封装起来&#xff0c;减少重复代码 一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个模块实现特定的功能。 2&#xff0c;函数的定义 函数的定义一般主要有五个步骤&#xff1a; 1&#xff0c;返回…

macOS修改默认时区显示中国时间

默认时区不是中国,显示时间不是中国时间 打开终端 ,删除旧区,并复制新时区到etcreb sudo -rm -rf /etc/localtime sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 重启系统后时间显示为中国时间

日志记录logging

文章目录 1. logging基础使用1.1 日志的6个级别1.2 logging.basicConfig1.3 案例 2. logging的高级应用2.1 记录器Logger2.2 处理器- Handler2.3 格式器- Formatter2.4 创建关联2.4 案例 3.在项目中的应用3.1 定义全局使用的logger对象3.2 使用案例 参考 1. logging基础使用 1…

【Linux】配置dns主从服务器,能够实现正常的正反向解析

​​​​​​1、首先&#xff0c;在主服务器上配置DNS解析器。打开配置文件/etc/named.conf&#xff0c;添加以下内容&#xff1a; zone"example.com" IN {type master;file "example.com.zone";allow-transfer { slave_ip_address: }; };zone"xx.16…

减少 LLM 幻觉方法--CoVe

​来自于 Meta AI&#xff0c;原文链接&#xff1a;https://arxiv.org/abs/2309.11495 LLM 经常遇到的主要问题就是幻觉&#xff0c;减少幻觉的方法大致可分为三类&#xff1a;训练时校正、生成时校正和通过增强&#xff08;使用工具&#xff09;进行校正。 在训练时校正的方法…

burp靶场--文件上传

burp靶场–文件上传 https://portswigger.net/web-security/file-upload/lab-file-upload-remote-code-execution-via-web-shell-upload 1.文件上传 1、原理&#xff1a;文件上传漏洞是指Web服务器允许用户将文件上传到其文件系统&#xff0c;而不充分验证文件的名称、类型、…

SpringMVC环境搭配

概述 Spring MVC是Spring Framework提供的Web组件&#xff0c;全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能 mvc是什么 MVC是一种软件架构思想&#xff0c;把软件按照模型&#xff0c;视图&#xff0c;控制器来划分…

linux基础学习(5):yum

yum是为了解决rpm包安装依赖性而产生的一种安装工具 1.yum源 1.1配置文件位置 yum源的配置文件在/etc/yum.repos.d/中 *Base源是网络yum源&#xff0c;也就是需要联网才能使用的yum源。默认情况下&#xff0c;系统会使用Base源 *Media源是光盘yum源&#xff0c;是本地yum源…

如何防止你的 Goroutine 泄露 Part2

文章目录 简述NumGoroutine演示案例pprofruntime/pprofhttp/net/pprof gopsLeak Test总结参考资料 上篇 文章说到&#xff0c;防止 goroutine 泄露可从两个角度出发&#xff0c;分别是代码层面的预防与运行层面的监控检测。今天&#xff0c;我们来谈第二点。 简述 前文已经介…