C++模板方法模式

news2024/9/26 7:16:10

文章目录

      • 1. 定义抽象基类(Abstract Class)
      • 2. 实现具体子类(Concrete Class)
      • 3. 使用模板方法
      • 模板方法模式的优点
      • 模板方法模式的应用场景
      • 注意事项
      • 实现示例
        • 抽象类(模板)
        • 具体实现类
        • 客户端代码
      • 总结

模板方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。这种模式非常适合需要控制算法流程,同时允许子类自定义部分行为的场景。

在C++中实现模板方法模式的基本步骤如下:

1. 定义抽象基类(Abstract Class)

首先,定义一个抽象基类,这个基类中包含了一个或多个模板方法和一些抽象方法或具体方法。模板方法定义了算法的整体框架,而抽象方法则是留给子类实现的。

class AbstractClass {
public:
    // 模板方法,定义了算法的骨架
    void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
    }

    // 抽象方法,由子类实现
    virtual void primitiveOperation1() = 0;
    
    // 可能还有其他抽象或具体方法
    virtual void primitiveOperation2() {
        // 默认实现
    }
protected:
    // 可能包含受保护的辅助方法
};

2. 实现具体子类(Concrete Class)

然后,创建抽象基类的子类,并实现其中的抽象方法。子类可以根据需要重写具体方法,但模板方法的结构保持不变。

class ConcreteClassA : public AbstractClass {
public:
    void primitiveOperation1() override {
        // 实现具体操作1
    }
    
    // 如果需要,也可以重写primitiveOperation2
};

class ConcreteClassB : public AbstractClass {
public:
    void primitiveOperation1() override {
        // 实现与ConcreteClassA不同的操作1
    }
};

3. 使用模板方法

客户端代码仅需调用模板方法,而无需知道算法的具体实现细节,提高了代码的抽象层次和复用性。

int main() {
    AbstractClass* a = new ConcreteClassA();
    a->templateMethod();
    delete a;

    AbstractClass* b = new ConcreteClassB();
    b->templateMethod();
    delete b;

    return 0;
}

在这个例子中,templateMethod是模板方法,它定义了执行操作的顺序,而primitiveOperation1primitiveOperation2是抽象方法,由子类实现具体的业务逻辑。这样,我们可以在不修改模板方法的情况下,通过更换不同的子类来改变算法的部分步骤,实现了算法的结构稳定性和步骤可变性的良好平衡。

模板方法模式的优点

  1. 代码复用:模板方法模式在一个类中定义了算法的骨架,而将一些步骤延迟到子类中实现,这使得相同的基本算法可以有不同的具体实现,提高了代码的复用性。

  2. 封装不变部分:将算法中的不变部分(算法的框架)封装在基类的模板方法中,确保了算法整体结构的稳定性和一致性。

  3. 扩展性好:新增新的具体实现时,只需要添加新的子类并实现相应的抽象方法,而不需要修改现有的类库代码,符合开闭原则。

  4. 行为控制:父类可以通过控制模板方法中的逻辑顺序,来控制子类的行为,增强了对系统行为的集中控制。

模板方法模式的应用场景

  • 框架开发:许多软件框架会使用模板方法模式定义其核心流程,而将具体实现留给用户自定义。比如,Junit测试框架中的测试用例运行流程就是一个模板方法模式的例子。

  • UI框架:在图形用户界面(GUI)框架中,绘制组件或处理事件的流程往往是一个固定的模板,而具体的绘制内容或事件响应则由各个组件自己实现。

  • 数据库访问库:数据库操作通常包括打开连接、执行查询、处理结果集、关闭连接等固定步骤,这些步骤可以作为模板方法定义,而具体的SQL语句和结果处理由子类实现。

注意事项

  • 避免过度设计:虽然模板方法模式可以增加代码的灵活性和扩展性,但如果滥用可能导致系统结构过于复杂,增加了理解和维护的难度。

  • 性能考量:由于涉及到虚函数调用,模板方法模式在性能敏感的应用中可能需要权衡。虽然现代编译器的优化已经大大减少了这种开销,但在极端性能要求下仍需注意。

  • 设计决策:确定哪些部分作为模板方法,哪些部分留给子类实现,需要仔细考虑,以达到既灵活又不失控制的目的。

总之,模板方法模式是面向对象设计中一种非常实用的模式,适用于需要定义算法框架并允许子类对部分步骤进行定制化的场景。正确使用它可以显著提升代码的结构和可维护性。

实现示例

为了更好地理解模板方法模式,下面通过一个简单的例子来说明其应用:假设我们正在设计一个冲泡饮料的框架,无论是咖啡还是茶,冲泡过程都包含几个通用步骤(烧水、加入原料、搅拌、倒入杯中),但具体每个步骤的实现细节(如原料种类)根据不同饮料而异。

抽象类(模板)

首先,我们定义一个抽象类Beverage,它充当模板方法模式中的抽象模板角色,定义了冲泡饮料的整个流程框架。

public abstract class Beverage {
    // 模板方法,定义冲泡流程
    public final void brew() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    // 基本方法,由子类实现
    protected abstract void brew(); // 冲泡(咖啡或茶)
    protected abstract void addCondiments(); // 添加调料(奶、糖等)

    // 具体方法,已实现
    private void boilWater() {
        System.out.println("Boiling water");
    }

    private void pourInCup() {
        System.out.println("Pouring into cup");
    }

    // 钩子方法,可被子类重写以改变默认行为
    protected boolean customerWantsCondiments() {
        return true;
    }
}
具体实现类

然后,我们创建两个具体实现类,分别代表咖啡(Coffee)和茶(Tea),它们继承自Beverage类,并实现其中的抽象方法。

public class Coffee extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Brewing Coffee");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding Sugar and Milk to Coffee");
    }
}

public class Tea extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Steeping the Tea");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding Lemon");
    }
}
客户端代码

最后,客户端代码仅需实例化具体饮料类并调用brew()方法,无需关注冲泡的具体步骤。

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Coffee();
        beverage.brew();

        System.out.println("\n");

        beverage = new Tea();
        beverage.brew();
    }
}

总结

通过这个例子,我们可以看到模板方法模式如何将算法的骨架与具体实现细节分离开来,使得算法的整体结构保持不变的同时,允许子类对某些步骤进行定制,从而提高了代码的复用性和灵活性。

😍😍 大量H5小游戏、微信小游戏、抖音小游戏源码😍😍
😍😍试玩地址: https://www.bojiogame.sg😍😍
😍看上哪一款,需要源码的csdn私信我😍

————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

期望薪资25K,新浪微博测试4轮面试,没想到过了。。

一面60min 1、离职原因 2、简单的算法题,就是我会什么让写什么: 冒泡排序,二分查找(其实这么简单,我还是在指引下写出来的,自己实在太菜) 3、简历问答(随机抽几个点问&#xff0…

MySQL数据库语法(二)

一、数据库的创建 创建数据库CRATE DATABASE语法&#xff1a;CREATE DATABASE [IF NOT EXISTS]数据库名;功能&#xff1a;用给定的名字创建一个数据库如果数据库已经存在&#xff0c;发生一个错误。查看创建数据库&#xff1a;SHOW CREATE DATABASE <数据库名>&#xff…

Oracle数据库操作问题汇总

一、简介 Oracle Database&#xff0c;又名Oracle RDBMS&#xff0c;或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是世界上流行的关系数据库管理系统&#xff0c;系统可移植性好、使用方便、功能强&…

【数据结构】快速排序(详解)

目录 快速排序 历史&#xff1a; 基本思想&#xff1a; 主框架&#xff1a; 下面解释实现单次排序的几种版本&#xff1a; 1.Hoare版本 2. 挖坑法 3. 前后指针法 快速排序的实现包括递归与非递归&#xff1a; 1. 递归实现&#xff1a;&#xff08;即开头的基本框架&am…

工程机械比例阀电流采集方案——IPEhub2与IPEmotion APP

自从国家实施一带一路和新基建计划以来&#xff0c;工程机械的需求量呈现出快速增长的趋势。而关于工程机械&#xff0c;其比例阀的控制问题不容忽视。比例阀是一种新型的液压控制装置——在普通压力阀、流量阀和方向阀上&#xff0c;用比例电磁铁替代原有的控制部分&#xff0…

KEIL5鼠标右键查找定义或声明选项变灰色不可选

原因&#xff1a;我直接点的KEIL图标打开了昨天的工程 解决办法&#xff1a;关掉工程&#xff0c;重新从文件夹的路径打开 其他原因导致试试以下方法&#xff1a; 1.快捷键F12导航到目标位置 2.路径不能含有中文&#xff0c;改好后&#xff0c;shiftAltf12&#xff0c;更新搜索…

疑惑点:动作监听时this的含义:可以理解为接口的多态

全部代码&#xff1a; package test;import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random;public class test3 extends JFrame implements ActionListener {JButton jb1 new JButton("你点我啊&am…

纽曼硬盘隐藏文件丢失怎么恢复?介绍几种有效的方法

纽曼硬盘作为存储设备中的佼佼者&#xff0c;以其高性能和稳定性受到了广大用户的青睐。然而&#xff0c;在使用过程中&#xff0c;有时我们可能会遇到一些意想不到的问题&#xff0c;比如隐藏文件的丢失。这对于依赖这些文件进行工作或生活的人来说无疑是一个巨大的困扰。那么…

香橙派AI Pro测评--ROS及激光SLAM

文章目录 前言一、外形与质感二、软件测评1. 系统界面2. ROS安装3. ROS节点测试4. SLAM算法测试 总结 前言 今天刚收到了官方寄来的“香橙派 AI Pro”开发板&#xff0c;这篇文章将会对香橙派 AI Pro的外形、质感、运行速度进行一个测评&#xff0c;然后我会在这个开发板上安装…

四步简单操作:轻松将iCloud照片恢复到相册

随着智能手机的普及&#xff0c;我们的生活中越来越多的照片存储在了云端&#xff0c;其中iCloud提供了便捷的照片备份和存储服务。但有时候&#xff0c;我们可能会不小心删除了在iCloud上的照片&#xff0c;或者想要将iCloud中的照片恢复到手机相册中。 在这篇文章中&#xf…

I.MX6ULL Linux 点灯实验理论及汇编点灯

系列文章目录 I.MX6ULL Linux C语言开发 I.MX6ULL Linux 点灯实验理论 系列文章目录一、I.MX6ULL GPIO二、I.MX6ULL IO 命名三、I.MX6ULL IO 复用四、I.MX6ULL IO 配置五、I.MX6ULL GPIO 配置六、I.MX6ULL GPIO 时钟使能七、硬件原理分析八、实验程序编写 一、I.MX6ULL GPIO 一…

flutter 的webview中touchstart和touchend 执行异常问题解决

效果 背景 使用flutter 调用webview内网页&#xff0c;网页内容是监听touchstart和 touchend&#xff0c;触发不同是事件&#xff0c;但是发现每次长按都 手指抬起后 才会执行 touchstart和touchend&#xff0c;满足不了我的需求&#xff0c;我的需求是当手指按下 立即执行touc…

aws emr启动standalone的flink集群

关键组件 Client&#xff0c;代码由客户端获取并做转换&#xff0c;之后提交给JobMangerJobManager&#xff0c;对作业进行中央调度管理&#xff0c;获取到要执行的作业后&#xff0c;会进一步处理转换&#xff0c;然后分发任务给众多的TaskManager。TaskManager&#xff0c;数…

解决mybatis/mybatis plus报错:Invalid bound statement (not found) 的方法汇总

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题&#xff0c;即在mybatis中dao接口与mapper配置文件在做映射绑定的时候接口与xml不匹配&#xff0c;要么是找不到&#xff0c;要么是找到了却匹配不到。 我的问题是项目没有把最新的方法x…

操作系统实验--终极逃课方法

找到图片里的这个路径下的文件 &#xff0c;结合当前题目名称&#xff0c;把文件内容全部删除&#xff0c;改为print print的内容为下图左下角的预期输出的内容

Databend 开源周报第 146 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持 Expressio…

Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版

Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版 Rocky Linux 由 CentOS 项目的创始人 Gregory Kurtzer 领导 请访问原文链接&#xff1a;Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处…

20212313 2023-2024-2 《移动平台开发与实践》第5次作业

20212313 2023-2024-2 《移动平台开发与实践》第5次作业 1.实验内容 设计并开发一个地图应用系统。 该实验需提前申请百度API Key&#xff0c;调用接口实现百度地图的定位功能、地图添加覆盖物和显示文本信息。 2.实验过程 2.1 获取SHA1 &#xff08;1&#xff09;打开控制台…

【Python编程】给电脑安装最新的 Python3.12.3

笔者最近更换了新的Win11系统&#xff0c;安装最新的Python版本&#xff08;3.12.3&#xff09;尝尝鲜。据说这个版本存在一些漏洞&#xff0c;笔者将后续更新编程过程中的相关问题&#xff08;如果有&#xff09;。Python3.12.3的安装过程比较简单&#xff0c;在此进行说明。 …