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

模板方法模式(Template Method)

模式结构图

在这里插入图片描述

说明

基本方法模板方法的组成部分。基本方法分为一下三种:

  • 抽象方法
    • 由抽象类声明,由其具体子类实现。C++中就是纯虚函数。
  • 具体方法
    • 由抽象类或具体类声明并实现,子类可以进行覆盖也可以继承。C++中是虚函数。
  • 钩子方法
    • 由抽象类或具体类声明并实现,子类可能会加以扩展。

其中钩子方法比较特殊,通常在父类给出的实现是一个空实现,并以该实现作为方法的默认实现。当然,默认实现也可以是非空。

模板方法模式中,钩子方法分为两类。
第一类钩子方法可以与一些具体步骤“挂钩”,以确定在不同条件下执行模板方法中的不同步骤,这类钩子方法的返回值通常是boolean类型的,这类方法一般为isXXX(),用于对某个条件进行判断,如果条件满足则执行某一步骤,否则不执行。
如下所示:

void TemplateMethod::template()
{open();display();if(isPrint){print();}
}
bool TemplateMethod::isPrint()
{return true;
}

在代码中isPrint()是钩子方法,它可以决定print()方法是否执行,一般情况下,钩子方法返回值为true,如果不希望某方法执行,可以在其子类中覆盖钩子方法,将其返回值改为false。这种钩子方法可以控制方法的执行,对一个算法进行约束。

第二类钩子方法就是实现体为空的具体方法,子类可以根据需要覆盖或者继承这些钩子方法,与抽象方法相比,钩子方法的好处在于如果没有覆盖父类中定义的钩子方法,编译可以通过,但是如果没有覆盖父类中抽象方法,编译将报错。

子类的钩子方法覆盖父类的钩子方法,可以通过子类对父类方法的执行进行约束,实现对父类的反向控制。

模板方法模式适用场景

  1. 一次性实现一个算法的不变部分,并将可变行为留给子类来实现
  2. 各子类中公共的行为应被提取出来,并集中到一个公共父类中,以避免代码重复。首先需要识别现有代码中的不同之处,并且将不同之处分离为新的操作,然后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  3. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。
  4. 控制子类的扩展。模板方法只在特定点调用钩子方法,这样就只允许在这些点进行扩展,也就是说对于某些方法,可以通过钩子方法来进行扩展,而对于不能进行扩展的方法也可以将其定义为final方法,对算法的扩展进行有效的控制和约束。

扩展

  • 继承的使用
    • 在扩展抽象层时采用继承,具体类之间的复用 以及 抽象层之间的相互调用则使用关联关系。
  • 好莱坞原则
    • 子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。

实例

银行业务办理

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;class BankTemplateMethod {
public:virtual ~BankTemplateMethod() = default;virtual void take_number() final { cout << "取号" << endl;};virtual void transact() = 0;virtual void evaluate() final { cout << "反馈评分" << endl; };virtual void process() final {this->take_number();this->transact();this->evaluate();};
};class Deposit : public BankTemplateMethod {
public:void transact() override { cout << "存款" << endl;}
};class Withdraw : public BankTemplateMethod {
public:void transact() override { cout << "取款" << endl; }
};class Transfer : public BankTemplateMethod {
public:void transact() override { cout << "转账" << endl; }
};int main (void)
{vector<BankTemplateMethod *> banks{new Deposit(),new Withdraw(),new Transfer()};for (auto i : banks) {i->process();cout << "\n";}for (auto i : banks) {delete i;}
}

相关文章:

模板方法模式(Template Method)

模式结构图 说明 基本方法是模板方法的组成部分。基本方法分为一下三种&#xff1a; 抽象方法 由抽象类声明&#xff0c;由其具体子类实现。C中就是纯虚函数。 具体方法 由抽象类或具体类声明并实现&#xff0c;子类可以进行覆盖也可以继承。C中是虚函数。 钩子方法 由抽象类…...

C C++ typedef的使用

一、为基本数据类型起别名 typedef int myint; myint x 5; "myint"是"int"的别名&#xff0c;可以使用"myint"来代替"int"声明变量&#xff0c;这个很好理解&#xff0c;但是也很少有人这么用吧。 二、为结构体起别名 …...

Laravel框架03:DB类操作数据库

Laravel框架03&#xff1a;DB类操作数据库一、概述二、数据表的创建与配置三、增删改操作1. 增加信息2. 修改数据3. 删除数据四、查询操作1. 取出基本数据2. 取出单行数据3. 获取一个字段的值4. 获取多个字段的值5. 排序6. 分页五、执行任意的SQL语句一、概述 按照MVC的架构&a…...

数据结构期末复习总结(前章)

作者的话 作为一名计算机类的学生&#xff0c;我深知数据结构的重要性。在期末复习前&#xff0c;我希望通过这篇博客给大家一些复习建议。希望能帮助大家夯实数据结构的基础知识&#xff0c;并能够更好地掌握数据结构和算法的应用。 一、绪论 数据&#xff1a;信息的载体&am…...

设计环形队列

文章目录1.思路分析1.1队列空满分析1.2出队分析2.循环队列设计1.思路分析 1.1队列空满分析 首先我们假设一个长度为4的环形队列 队头front 队尾rear 当队列为空时 frontrear 当队列满时 frontrear 所以我们无法判断队列是满的或者空的 因此我们多加入一个空间使队列长度为5&am…...

面向对象之-接口鉴权

1 需求 1.1 需求背景 为了保证接口调用的安全性&#xff0c;我们希望设计实现一个接口调用鉴权功能&#xff0c;只有经过认证之后的系统才能调用我们的接口&#xff0c;没有认证过的系统调用我们的接口会被拒绝。 2 需求分析 2.1 基础分析 对于如何做鉴权这样一个问题&…...

Python 多进程多线程线程池进程池协程

目录 一、线程与进程很简单的介绍 1.1 线程与进程的区别 二、多进程Process 2.1 多进程与多线程的区别 2.2 多进程为啥要使用队列 2.3 控制进程运行顺序 2.3.1 join &#xff0c; 2.3.1 daemon 守护进程 2.4 进程id 2.5 进程 存活状态is_alive() 2.5 实现自定义多…...

【自然语言处理】基于句子嵌入的文本摘要算法实现

基于句子嵌入的文本摘要算法实现人们在理解了文本的含义后&#xff0c;很容易用自己的话对文本进行总结。但在数据过多、缺乏人力和时间的情况下&#xff0c;自动文本摘要则显得至关重要。一般使用自动文本摘要的原因包括&#xff1a; 减少阅读时间根据摘要&#xff0c;选择自…...

fiddler抓包

一、工具介绍Fiddler是一个通过代理的方式来进行抓包工具&#xff0c;运行时会在本地建立一个代理服务&#xff0c;默认地址&#xff1a;127.0.0.1:8888。Fiddler开启之后&#xff0c;配置本机代理&#xff0c;再打开IE浏览器&#xff0c;IE的PROXY会自动变成127.0.0.1:8888&am…...

【Linux】网络套接字编程

前言 在掌握一定的网络基础&#xff0c;我们便可以先从代码入手&#xff0c;利用UDP协议/TCP协议进行编写套接字程序&#xff0c;明白网络中服务器端与客户端之间如何进行连接并且通信的。 目录 一、了解源目的IP、端口、网络字节序、套接字 端口号&#xff1a; 套接字&…...

break与continue关键字

1.概述 不知道大家有没有这样一种感受哈&#xff0c;有的时候容易混淆break语句和continue语句的用法&#xff0c;总是模棱两可&#xff0c;不敢确定自己是否使用正确了。正好&#xff0c;我们本篇的重点就是break和continue关键字的用法。 2.使用场景 Java中为啥会诞生break…...

kafka使用入门案例与踩坑记录

每次用到kafka时都会出现各种奇怪的问题&#xff0c;综合实践&#xff0c;下面汇总下主要操作步骤&#xff1a; Docker镜像形式启动 zookeeper启动 docker run -d --name zookeeper -p 2181:2181 -t wurstmeister/zookeeperkafka启动 docker run --name kafka01 -p 9092:909…...

系统启动太慢,调优后我直呼Nice

问题背景最近在负责一个订单系统的业务研发&#xff0c;本来不是件困难的事。但是服务的启动时间很慢&#xff0c;慢的令人发指。单次启动的时间约在10多分钟左右&#xff0c;基本一次迭代、开发&#xff0c;大部分的时间都花在了启动项目上。忍无可忍的我&#xff0c;终于决定…...

java知识点

文章目录异常写法JVM加载反射访问private调用方法动态代理注解元数据&#xff1a;TargetRetention元注解泛型编写泛型擦拭法局限通配符无限定通配符(<?>)集合重写方法和实现类IO流字节与字符转换同步和异步可以设置编码的类Print*类Files时间与日期时区一种二种三种异常…...

文件的打开关闭和顺序读写

目录 一、文件的打开与关闭 &#xff08;一&#xff09;文件指针 &#xff08;二&#xff09; 文件的打开和关闭 二、文件的顺序读写 &#xff08;一&#xff09;fputc 1. 介绍 2. 举例 &#xff08;二&#xff09;fgetc 1. 介绍 2. 举例1 3. 举例2 &#xff08;三&…...

(十八)操作系统-进程互斥的软件实现方法

文章目录一、知识总览二、单标志法三、双标志先检查法四、双标志后检查法五、Peterson算法六、总结一、知识总览 二、单标志法 算法思想&#xff1a;两个进程在访问临界区后&#xff0c;会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进…...

2023年三月份图形化一级打卡试题

活动时间 从2023年3月1日至3月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; 小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 小朋友做完题目后&#xff0c;截图到朋友圈打卡并把打卡的截图发到活动群…...

linux 防火墙管理-firewalld

什么是Firewalld 当前很多linux系统中都默认使用 firewalld&#xff08;Dynamic Firewall Manager of Linux systems&#xff0c;Linux系统的动态防火墙管理器&#xff09;服务作为防火墙配置管理工具。 “firewalld”是firewall daemon。它提供了一个动态管理的防火墙&#x…...

2023年最新大厂开发面试题(滴滴,华为,京东,腾讯,头条)

2023年最新大厂开发面试题&#xff01;&#xff01;&#xff01; 滴滴篇 B树、B-树的区别? 数据库隔离级别&#xff0c;幻读和不可重复读的区别&#xff1f; 有 hell, well, hello, world 等字符串组&#xff0c;现在问能否拼接成 helloworld&#xff0c;代码实现。 快排算…...

2023年三月份图形化三级打卡试题

活动时间 从2023年3月1日至3月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; 小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 小朋友做完题目后&#xff0c;截图到朋友圈打卡并把打卡的截图发到活动群…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...