常见手撕项目C++
常见手撕项目C++
- 设计模式
- 单例模式
- 饿汉模式
- 懒汉模式
- 策略模式
- 策略接口
- 实现具体的策略(虚函数重写)
- 定义上下文
- 用户调用
设计模式
单例模式
单例模式是一种常用的软件设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点来获取该实例。
- 优点:
- 资源控制:单例模式能够确保一个类只有一个实例存在,这对于控制资源的使用非常有用,如配置文件的读取、数据库的连接等,可以避免由于多个实例造成的资源浪费或冲突。
- 全局访问点:单例对象可以被全局访问,方便其他对象对其进行访问,而无需持有单例类的引用。
- 数据共享:由于整个应用程序共享一个单例实例,它自然地提供了一个共享数据的环境,这在某些场合下是非常有用的。
- 缺点:
- 全局变量(同步)问题:单例模式本质上提供了一个全局可访问的实例,但全局变量(或对象)容易被误用,特别是涉及多个线程进行访问的时候,还会出现同步问题。
- 违背单一职责原则:单例类除了管理自己的实例外,还承担了业务逻辑的职责,违反了单一职责原则。
介绍完单例模式,我们来看看单例模式的两种实现方式,分别是饿汉模式与懒汉模式。
饿汉模式
饿汉模式指的是单例实例在程序启动时就立即创建(迫不及待的感觉)。这种方式避免了线程安全问题,但可能会增加程序的启动时间,同时如果实例最终未被使用,则会造成资源的浪费。
class EagerSingleton{
private:// 将自己的实例化对象申明为静态资源static EagerSingleton instance;
protected:// 隐藏自己的构造函数以及析构函数,防止用户调用EagerSingleton() = default; // 这里构造函数设置为默认EagerSingleton(const EagerSingleton&) = default;EagerSingleton& operator= (const EagerSingleton&) = default;~EagerSingleton() = default;
public:EagerSingleton& getInstance(){return instance;}
}// 静态的私有成员变量可以在类外进行初始化(一般在main()函数之前进行初始化),在这里,你可以理解instance是类内成员,可以访问私有以及保护成员。
EagerSingleton EagerSingleton::instance();
懒汉模式
懒汉模式指的是单例实例在第一次被使用时才进行创建(不叫我,那我就懒,不创建)。这种方式可以减少资源的消耗,但需要考虑线程安全问题(例如多个线程同时是第一次使用,所以一般需要锁)。
#include <mutex>class lazySingleton{
private:static lazySingleton* instance; // 懒汉模式一般使用指针static mutex my_mu; // 考虑到线程安全,需要有锁。
protected:// 不给用户调用构造函数和析构函数的机会lazySingleton() = default;lazySingleton(const lazySingleton&) = default;lazySingleton& operator=(const laySingleton&) = default;~lazySingleton() = default;
public:lazySingleton* getInstance(){if(instance == nullptr){ // 第一次检查std::lock_guard<std::mutex> lock(my_mu); //作用域锁,离开作用域后,自动解锁if(instance == nullptr){ // 第二次检查instance = new lazySingleton();}}return *this;}// my_mu会在这里结束后,自动解锁
}// 静态成员变量类外初始化
lazySingleton lazySingleton::instance = nullptr;
lazySingleton lazySingleton::my_mu; // 调用锁的自动初始化方法
这里可能会好奇,为什么需要两次判断instance == nullptr
?
- 第一次检查 (
instance == nullptr
)
第一次检查是在锁外进行的。这个检查的目的是避免在单例实例已经创建之后的每次调用都需要进行昂贵的锁操作。如果实例已经存在,就直接返回实例,这样大部分时间可以避免锁的开销。 - 获取锁
如果第一次检查发现实例为nullptr,即单例尚未被创建,那么就需要进入同步块(通过获取锁)来确保只有一个线程可以创建单例实例。这是必要的,因为可能有多个线程同时通过了第一次的nullptr检查。 - 第二次检查 (
instance == nullptr
)
即使线程成功获取了锁,仍然需要再次检查实例是否为nullptr。这是因为在当前线程等待锁的同时,可能有另一个线程已经获取了锁、创建了实例并释放了锁。第二次检查确保了即使在多个线程同时尝试创建单例实例的情况下,单例实例仍然是唯一的。
策略模式
策略模式是一种行为设计模式,它允许在运行时选择算法或行为的最佳策略。策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互换。这种模式让算法的变化独立于使用算法的客户。
策略接口
首先,要定义一个策略接口,表示可以执行的操作
class Strategy{
public:virtual ~Strategy(){};virtual void excute() const = 0; // 操作定义为纯虚函数
}
实现具体的策略(虚函数重写)
然后,利用继承,实现不同且具体的策略
class StrategyA : public Strategy{
public:void excute() const override{ //override 关键字表示一定是重写虚函数,避免出现覆盖的情况(如果有存在的话)cout << "StrategyA" << endl;}
}class StrategyB : public Strategy{
public:void excute() const override{ //override 关键字表示一定是重写虚函数,避免出现覆盖的情况(如果有存在的话)cout << "StrategyB" << endl;}
}class StrategyB : public Strategy{
public:void excute() const override{ //override 关键字表示一定是重写虚函数,避免出现覆盖的情况(如果有存在的话)cout << "StrategyB" << endl;}
}
定义上下文
接着,定义一个上下文类,用于从客户端接收策略,并使用它执行操作
#include <iostream>
#include <memory> // 智能指针共享库
using namespace std;class Context{
public:unique_ptr<Strategy> strategy; // 使用独占的智能指针// 使用右值引用来接收一个unique_ptr,并提供默认参数(即调用这个函数的时候可以不用传入参数)Context(unique_ptr<Strategy> &&strategy = {}): strategy(std::move(strategy)){}// 设置接口到底执行哪一个函数void setStrategy(unique_ptr<Strategy> &&strategy){strategy = std::move(strategy);}// 执行具体函数void excuteStrategy() const{if(strategy){strtegy->excute();}}
}
用户调用
int main(){// 需要注意make_unique<StrategyA>()是一个不具名的右值,所以可以正确调用右值构造函数Context context(make_unique<StrategyA>());context.excuteStrategy(); // 输出:StrategyA// 动态切换策略context.setStrategy(make_unique<StrategyB>());context.excuteStrategy(); // 输出:StrategyBcontext.setStrategy(make_unique<StrategyC>());context.excuteStrategy(); // 输出:StrategyCreturn 0;
}
相关文章:
常见手撕项目C++
常见手撕项目C 设计模式单例模式饿汉模式懒汉模式 策略模式策略接口实现具体的策略(虚函数重写)定义上下文用户调用 设计模式 单例模式 单例模式是一种常用的软件设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点来…...
创建一个批处理作业来处理大量数据,例如从数据库中读取数据并进行处理
创建一个批处理作业来处理大量数据,例如从数据库中读取数据并进行处理 要创建一个批处理作业来处理大量数据,您可以使用Spring Batch。Spring Batch是一个用于大规模批处理的框架,它提供了丰富的功能来处理复杂的批处理任务,如读…...
LeetCode 2.两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 …...
如何利用ChatGPT提升学术论文写作效率
ChatGPT无限次数:点击直达 如何利用ChatGPT提升学术论文写作效率 ChatGPT 是一种基于大规模预训练模型的自然语言处理工具,可以在各种文本生成任务中发挥作用,包括学术论文写作。利用ChatGPT,可以提高学术论文写作的速度和质量,帮…...
LLMs之Mistral:Mistral 7B v0.2的简介、安装和使用方法、案例应用之详细攻略
LLMs之Mistral:Mistral 7B v0.2的简介、安装和使用方法、案例应用之详细攻略 导读:Mistral AI首个7B模型发布于2023年9月,在基准测试中超越Llama 2 13B,一下子声名大振。Mistral 7B v0.2对应的指令调优版本Mistral-7B-Instruct-v0…...
深入解析Oracle数据库中的WITH AS(CTE)原理
Oracle数据库中的WITH AS子句(也称为公用表表达式CTE(Common Table Expression))是一种高级查询构造工具,它允许在一条SQL语句的开始部分定义临时的结果集(或称子查询),这个结果集可以被随后的查询主体多次…...
Linux 环境安装 Elasticsearch 8.X
安装前说明 首先确定操作系统,在Linux发行版上执行uname -a查看具体系统。我是Ubuntu系统,可以用直接用apt-get安装,也可以下载tar.gz包手动安装。使用apt-get安装更方便快速,但不同的文件会被安装到不同的目录,不方便…...
Java零基础-集合:函数式接口
哈喽,各位小伙伴们,你们好呀,我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。 我是一名后…...
Redis Scan指令解析与使用示例
Redis Scan指令解析与使用示例 概念 想要从redis key列表中找到某个key,redis提供了一个简单粗暴的指令keys用来列出满足查询条件的所有key。 keys redis* keys redis*keykey指令非常简单,只要提供一个简单的正则表达式即可,但是有两个明显的…...
Qt+OpenGL入门教程(三)——绘制三角形
通过前两篇文章的学习,我想大家应该有了基本的理解,我们接下来实操一下。 创建Qt OpenGL窗口 QOpenGLWidget QGLWidget是传统QtOpenGL模块的一部分,与其他QGL类一样,应该在新的应用程序中避免使用。相反,从Qt5.4开始…...
springcloud基本使用(搭建eureka服务端)
创建springbootmaven项目 next next finish创建成功 删除项目下所有文件目录,只保留pox.xml文件 父项目中的依赖: springboot依赖: <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-s…...
第十二章:预处理命令
文章目录 第十二章:预处理命令宏定义无参宏定义带参数的宏定义 文件包含处理 第十二章:预处理命令 作用:由编译预处理程序对程序中的特殊命令作出解释,以产生新的源程序对其进行正式编译 C语言与其他语言的重要区别就是可以使用预…...
Game Audio Programming
音频编程时游戏开发中最容易忽略,学习资源又是很少的环节。接下来,你将和我探索人耳的工作机制。 what is sound? 我们可以解释电视机是如何通过眼睛传递视觉信息的,但却往往无法对听觉信息做出类似的解释。 对声音的科学研究被称为声学&…...
高风险IP来自哪里:探讨IP地址来源及其风险性质
在网络安全领域,高风险IP地址是指那些可能涉及恶意活动或网络攻击的IP地址。了解这些高风险IP地址的来源可以帮助网络管理员更好地识别和应对潜在的安全威胁。本文将探讨高风险IP地址的来源及其风险性质,并提供一些有效的应对措施。 风险IP查询…...
【每日跟读】常用英语500句(300~400)
【每日跟读】常用英语500句 I had to take a shower. 我洗了个澡 Go on in. 赶紧进去吧 Hold up. 等一下 They seem like nice people. 他们看起来像好人 Such a wonderful age. 如此美好的年纪 That’s very impressive. 真厉害 I can see that. 看得出来 You should …...
设计模式(7):装饰器模式
一.装饰器模式职责: 动态的为一个对象增加新的功能;装饰器是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。 …...
Flink SQL填坑记3:两个kafka数据关联查询
在一个项目中,实时生成的统计数据需要关联另外一张表(并非维表),需要统计的数据表是Kafka数据,而需要关联的表,由于不是维度,不能按照主键查询,所以如果放在MySQL上,将存在严重的性能问题,这个时候我想到用将两张表的数据都生成为Kafka数据,然后进行Join操作。中途发…...
移动平台实时动态多点光源方案:Cluster Light
一、什么是 Cluster Light,它具体如何实现多点光源效果? 对于移动设备,如何支持场景中大量的实时点光源一直以来都是比较棘手的问题,因此对于过去,往往有如下两种常规方案: 静态点光源直接烘焙࿰…...
2024年03月CCF-GESP编程能力等级认证C++编程八级真题解析
本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 为丰富食堂菜谱,炒菜部进行头脑风暴。肉类有鸡肉、牛肉、羊肉、猪肉4种,切法有肉排、肉块、肉末3种,配菜有圆白菜、油菜、…...
(十一)图像的罗伯特梯度锐化
环境:Windows10专业版 IDEA2021.2.3 jdk11.0.1 OpenCV-460.jar 系列文章: (一)PythonGDAL实现BSQ,BIP,BIL格式的相互转换 (二)BSQ,BIL,BIP存储格式的相互转换算法 (三…...
实验九 枚举问题(运算模拟)
实验名称:实验九 枚举问题(运算模拟) 实验目的:熟练掌握一些枚举问题的处理方法。 实验内容: 问题描述:(乘积为n个1的数字游戏)两位计算机爱好者在进行“积为n个1的数字游戏”&a…...
2024 年 AI 辅助研发趋势:从研发数字化到 AI + 开发工具 2.0,不止于 Copilot
1. 背景介绍 随着人工智能技术的飞速发展,AI在软件开发领域的应用越来越广泛。从最初的代码补全、错误提示,到现在的代码生成、自动化测试,AI正在逐步改变软件开发的模式。2024年,AI辅助研发的趋势已经从研发数字化向AI开发工具2…...
UE5数字孪生系列笔记(三)
C创建Pawn类玩家 创建一个GameMode蓝图用来加载我们自定义的游戏Mode新建一个Pawn的C,MyCharacter类作为玩家,新建一个相机组件与相机臂组件,box组件作为根组件 // Fill out your copyright notice in the Description page of Project Set…...
ASR-LLM-TTS 大模型对话实现案例;语音识别、大模型对话、声音生成
参考:https://blog.csdn.net/weixin_42357472/article/details/136305123(llm+tts) https://blog.csdn.net/weixin_42357472/article/details/136411769 (asr+vad) 这里LLM用的是chatglm;电脑声音播报用的playsound 1、实时语音识别版本 注意:暂时这项目有个缺陷就是tts…...
主干网络篇 | YOLOv8更换主干网络之EfficientNet
前言:Hello大家好,我是小哥谈。EfficientNet是一种高效的卷积神经网络架构,由Mingxing Tan和Quoc V. Le在2019年提出,其设计思想是在不增加计算复杂度的情况下提高模型的准确性。它引入了一个称为"复合系数"的概念,该系数用于同时缩放网络的深度、宽度和分辨率。…...
Web开发-Django学习笔记
客户端如何获取服务端的数据信息? 通常 是 HTTP网络协议,通过网络传输数据信息。 客户端通过HTTP协议发送请求信息给服务端,并从服务端接收响应信息。 Web 前端开发: (HTML、CSS、JS)文件部署在后端服务…...
关于深度学习的 PyTorch 项目如何上手分析?从什么地方切入?
文章目录 PyTorch 项目分析1.背景2.分析流程 PyTorch 项目分析 1.背景 当我们拿到一个 PyTorch 的深度学习项目时,应该怎么入手?怎么去查看代码? 2.分析流程 首先阅读对应项目的 README.md 文件。通过阅读 README.md ,一般可以…...
JavaEE企业开发新技术4
2.16 模拟Spring IOC容器功能-1 2.17 模拟Spring IOC容器功能-2 什么是IOC? 控制反转,把对象创建和对象之间的调用过程交给Spring框架进行管理使用IOC的目的:为了耦合度降低 解释: 模仿 IOC容器的功能,我们利用 Map…...
CSS使用JS变量
1. CSS变量 CSS 变量(也称为自定义属性)允许我们在 CSS 中定义可重复使用的值,并将其应用于不同的选择器。为了创建一个 CSS 变量,我们需要使用 -- 前缀,然后可以像常规属性一样使用它。 :root {--primary-color: bl…...
拆分巨石:将MVPS和MVAS应用于遗留应用程序——可持续架构(六)
前言 MVP 和 MVA 的概念不仅适用于新应用程序;它们提供了一种新颖的方式来审视对遗留系统的范围变更,以防止过快地承担过多的变化 - 参见图1。MVA 可以帮助组织评估和更新其技术标准,通过展示新技术如何真正对支持 MVP 至关重要。创建 MVA 可…...
做六级真题的网站/婚恋网站排名前10
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/zjx18915341085/article/details/79715075一、准备工作1、修改环境变量,能够找到qmake&am…...
如何做网站访百度联盟/网站快速排名互点软件
在Stata/SE 16.0中,您可以使用以下命令将dta格式数据存储为Excel: export excel using filename.xlsx, replace其中,filename.xlsx是要存储的Excel文件的名称,replace选项指示如果该文件已经存在,则将其替换。 请注意&…...
wordpress后天地址/西安百度竞价代运营
在动手写这篇之前,在朋友圈做了个调查,看到大家对百度轻应用的热情很高。 针对大家提的问题,和我对轻应用的理解,整理如下: 1、何为轻应用、微应用,及区别在哪里? 轻应用是在2013年百度世界大会…...
wordpress 获取置顶文章/什么网站可以发布广告
WebStorm 之 Cordova 环境搭建 原文:WebStorm 之 Cordova 环境搭建一、环境搭建 Cordova 环境配置之前,应先下载安装 Node.js ,中文官网:http://nodejs.cn/。 以管理员身份运行 cmd 命令行工具: 1、查看 Node.js 是否已安装成功&a…...
商丘做网站推广的公司/定制化网站建设
import tensorflow as tf import numpy as np# 在这个例子中,我们的目标就是要找到合适的b和k,使得该线性模型能够把上面的样本给表示出来# 第一、使用Numpy生成一百个随机点,这就是样本 x_data np.random.rand(100) y_data x_data*0.1 0.2# 第二、构…...
哪个全球购网站做的好/企业网上的推广
1. 概述 路由 是MVC架构的Web框架中相当重要的一个概念,也是本节课程的重点。顾名思意,路由就是在迷茫中找出一条路的意思。在Flask框架中,路由 就表示为用户请求的URL找出其对应的处理函数之意。在本节课程,我们将主要从以下几个…...