C++设计模式|创建型 1.单例模式

news2024/12/28 18:07:53

1.什么是单例模式?

单例模式的的核⼼思想在创建类对象的时候保证⼀个类只有⼀个实例,并提供⼀个全局访问点来访问这个实例。

  • 只有⼀个实例的意思是,在整个应⽤程序中,只存在该类的⼀个实例对象,⽽不是创建多个相同类型的对象。
  • 全局访问点的意思是,为了让其他类能够获取到这个唯⼀实例,该类提供了⼀个全局访问点(通常是⼀个静态⽅法),通过这个⽅法就能获得实例。

 2.单例设计模式的优点

  • 全局控制:保证只有⼀个实例,这样就可以严格的控制客户怎样访问它以及何时访问它,简单的说就是对唯⼀实例的受控访问。
  • 节省资源:也正是因为只有⼀个实例存在,就避免多次创建了相同的对象,从⽽节省了系统资源,⽽且多个模块还可以通过单例实例共享数据。
  • 懒加载:单例模式可以实现懒加载,只有在需要时才进⾏实例化,能够提⾼程序的性能。

3. 单例设计模式的要求

  • 私有的构造函数:C++类的私有权限使得构造函数只能在类内部被访问,防⽌外部代码直接创建类的实例。
  • 私有的静态实例变量:C++中类的静态成员(变量或函数)归类所有,是类的所有实例所共享的。将实例变量设为静态,表明这个类的实例变量唯一。设为私有,辨明该实例在类外必须通过公有的接口来获得。
  • 公有的静态方法getInstance():这个就是上面所述的获取唯一实例的借口。静态也使其具有唯一的性质。

 4.单例模式的实现

按照实例创建的时机,单例模式有着多种实现方式,包括懒汉式、饿汉式等。

饿汉式:在类加载时就已经完成了实例的创建,不管后面创建的实例有没有使用,先创建再说,所以叫做 “饿汉”。

懒汉式:只有在请求实例时才会创建,如果在首次请求时还没有创建,就创建一个新的实例,如果已经创建,就返回已有的实例,意思就是需要使用了再创建,所以称为“懒汉”。

多线程环境下,由于饿汉式在程序启动阶段就完成了实例的初始化,因此不存在多个线程同时尝试初始化实例的问题,但是懒汉式中多个线程同时访问 getInstance() 方法并且在同一时刻检测到实例没有被创建,就可能会同时创建实例,从而导致多个实例被创建,这种情况下我们可以采用一些同步机制,例如使用互斥锁来确保在任何时刻只有一个线程能够执行实例的创建。

5.C++代码实战

小明的购物车icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1074

题目描述:

小明去了一家大型商场,拿到了一个购物车,并开始购物。请你设计一个购物车管理器,记录商品添加到购物车的信息(商品名称和购买数量),并在购买结束后打印出商品清单。(在整个购物过程中,小明只有一个购物车实例存在)。

输入描述

输入包含若干行,每行包含两部分信息,分别是商品名称和购买数量。商品名称和购买数量之间用空格隔开。

输出描述

输出包含小明购物车中的所有商品及其购买数量。每行输出一种商品的信息,格式为 "商品名称 购买数量"。

输入示例

Apple 3
Banana 2
Orange 5

输出示例 

Apple 3
Banana 2
Orange 5

提示信息 

本道题目请使用单例设计模式: 

使用私有静态变量来保存购物车实例

使用私有构造函数防止外部直接实例化

思路分析:

题目要求使用单例模式设计一个购物车管理器,那么这个管理器的类就是需要进行单例设置的类。包括私有的构造函数、私有的静态实例以及公有的实例获取方法接口。

代码实现:

#include<iostream>
#include<map>
#include<string>
using namespace std;

class ShoppingManager{
private:
    //私有的构造函数防止类外实例化
    ShoppingManager(){}
    
    //使用map作为购物车存放商品名级商品数量
    map<string,int> cart;
    
public:
    //公有的静态接口函数,获取实例
    static ShoppingManager&  getInstance()
    {
        //静态实例。由于构造函数私有,所以该实例也算是必须类内调用构造函数才能得到。带有私有的含义
        static ShoppingManager instance;  
        return instance;
    }
    
    //析构函数
    ~ShoppingManager(){}
    
    //将商品添加到购物车。const保证数据不会误改,引用&避免拷贝
    void addGoods(const string& name,const int& num)
    {
        cart[name] += num;  //+=保证同名商品数量叠加而不是重写覆盖
    }
    
    //查看购物车.  注意const的作用
    void viewCart() const 
    {
        //正常访问
        // for(auto it = cart.begin(); it!= cart.end();++it)  {
        //     cout<<it->first<<" "<<it->second<<endl;
        // }
        
        //避免迭代器修改的访问。注意,迭代器类似指针,所以访问map的内容用->
        // for(map<string,int>::const_iterator it = cart.cbegin(); it!=cart.cend();++it)
        // {
        //     cout<<it->first<<" "<<it->second<<endl;
        // }
        
        
        //如果是范围for语句,则得到的是map的每一个成员,属于pair类型,用.点来访问内容
        for( const auto  & member: cart)
        {
            cout<<member.first<<" "<<member.second<<endl;
        }
    }
    
};

int main()
{
    string name;
    int num;
    //按行读数据,可以使用while循环配合cin
    while(cin>>name>>num)
    {
        //由于单例模式的构造函数私有,无法直接点用构造函数实例化,所以无法通过对象调用getInstance
        //因此,可以使用类名::getInstance()的方式来获取单例
        ShoppingManager & myCart = ShoppingManager::getInstance();
        myCart.addGoods(name,num);
    }
    // 输出购物车内容。
    const ShoppingManager& myCart = ShoppingManager::getInstance();
    myCart.viewCart();
    return 0;
}

    由于实例是静态的,所以它的生存周期会在程序运行结束才销毁,且唯一,存放在全局区,因此即使第一次创建实例时是在while循环里面,第二次再使用getInstance获取它时,仍能获取到这个唯一的实例,其数据为最近一次更改后的数据。构造函数也旨在第一次构建实例时调用了,myCart.viewCart()前面的那句的getInstance代码并没有调用构造函数。读者可以在构造函数里打印一句话用以验证这一点。

6.应用场景

  • 资源共享

        多个模块共享某个资源的时候,可以使用单例模式,比如说应用程序需要一个全局的配置管理器来存储和管理配置信息、亦或是使用单例模式管理数据库连接池。

  • 只有一个实例

        当系统中某个类只需要一个实例来协调行为的时候,可以考虑使用单例模式, 比如说管理应用程序中的缓存,确保只有一个缓存实例,避免重复的缓存创建和管理,或者使用单例模式来创建和管理线程池。

  • 懒加载

        如果对象创建本身就比较消耗资源,而且可能在整个程序中都不一定会使用,可以使用单例模式实现懒加载

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

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

相关文章

spring boot整合Redis监听数据变化

一、前言 Redis提供了数据变化的通知事件&#xff0c;可以实时监测key和value的变化&#xff0c;客户端可以通过订阅相关的channel来接收这些通知事件&#xff0c;然后做相应的自定义处理&#xff0c;详细的介绍可以参考官方文档Redis keyspace notifications | Docs 使用Red…

NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估

目录 一、说明 二、Deepset SQUAD是个啥&#xff1f; 三、问答系统&#xff08;QA系统&#xff09;&#xff0c;QA系统在各行业的应用及基本原理 3.1 医疗 3.2 金融 3.3 顾客服务 3.4 教育 3.5 制造业 3.6 法律 3.7 媒体 3.8 政府 四、在不同行业使用QA系统的基本原理 五、关于…

uniapp uview里面的u-navbar结合u-sticky组件的使用

导航栏自定义加需要吸顶产生的问题 如上图直接使用并不能出现tab栏吸顶效果&#xff0c;那是由于u-sticky组件吸顶时与顶部的距离默认为0 那么做如下处理 <u-sticky :offset-top"navbarHeight()"><u-tabs :list"helpTabList" active-color"…

Excel/WPS超级处理器,提取汉字/字母/数字

在职场工作中&#xff0c;经常会遇到单元格中有汉字&#xff0c;数字&#xff0c;字母三者的自由组合&#xff0c;但往往只需要其中的一者&#xff0c;如何快速提取呢&#xff0c;超级处理器&#xff0c;提供了4个功能可选。 超级处理器下载与安装 1&#xff09;分离字符 将…

【MySQL】事务篇

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 目录 本系列专栏 1. 什么是事务 2. 事务的特征 原子性&#xff08;Atomicity&#xff09; 一致性&#xff08;Consistency&#xff09; 隔离性&…

【MYSQL】索引机制概述

由于MySQL是作为存储层部署在业务系统的最后端&#xff0c;所有的业务数据最终都要入库落盘&#xff0c;但随着一个项目在线上运行的时间越来越久&#xff0c;数据库中的数据量自然会越来越多&#xff0c;而数据体积出现增长后&#xff0c;当需要从表查询一些数据时&#xff0c…

Argus DBM 一款开源的数据库监控工具,无需部署Agent

开箱即用 无需部署Agent&#xff0c;开箱即用。我们使用JDBC直连您的数据库&#xff0c;输入IP端口账户密码即可。 全平台支持 Argus目前支持对Mysql, PostgreSQL, Oracle等数据库类型的监控&#xff0c;我们也会尽快适配其它数据库&#xff0c;致力于监控所有数据库。我们提…

数仓维度建模

维度建模 数仓建模方法1. 范式建模法&#xff08;Third Normal Form&#xff0c;3NF&#xff09;2. 维度建模法&#xff08;Dimensional Modeling&#xff09;3. 实体建模法&#xff08;Entity Modeling&#xff09; 维度建模1. 事实表事实表种类事务事实表周期快照事实表累计快…

淘宝扭蛋机小程序:扭出惊喜,乐享购物新体验

在快节奏的现代生活中&#xff0c;人们总是在寻找新鲜、有趣的娱乐方式。淘宝扭蛋机小程序应运而生&#xff0c;为您带来前所未有的购物与娱乐结合新体验。在这里&#xff0c;每一次的扭动都充满惊喜&#xff0c;每一次的点击都带来乐趣&#xff0c;让您在购物的同时&#xff0…

VRRP(虚拟路由冗余协议)详解

VRRP-------虚拟路由冗余协议 在一个网络中&#xff0c;要做为一个合格的网络首先就要具备几种冗余&#xff0c;增加网络的可靠性。 这几种冗余分别为&#xff1a;线路冗余&#xff0c;设备冗余&#xff0c;网关冗余&#xff0c;UPS冗余 VRRP该协议就是解决网关冗余的。在二层…

总分410+专业130+国防科技大学831信号与系统考研经验国防科大电子信息与通信工程,真题,大纲,参考书。

好几个学弟催着&#xff0c;总结一下我自己的复习经历&#xff0c;希望大家复习少走弯路&#xff0c;投入的复习正比换回分数。我专业课831信号与系统130&#xff08;感觉比估分要低&#xff0c;后面找Jenny老师讨论了自己拿不准的地方也没有错误&#xff0c;心里最近也这经常回…

基于kintex UltraScale XCKU060的双路QSFP+光纤PCIe 卡

基于kintex UltraScale XCKU060的双路QSFP光纤PCIe 卡 一、板卡概述 本板卡系我司自主研发&#xff0c;基于Xilinx UltraScale Kintex系列FPGA XCKU060-FFVA1156-2-I架构&#xff0c;支持PCIE Gen3 x8模式的高速信号处理板卡&#xff0c;搭配两路40G QSFP接口&#xff…

分类算法——sklearn转换器和估计器(一)

转换器&#xff08;特征工程的父类&#xff09; 实例化&#xff08;实例化的是一个转换器类&#xff08;Transformer&#xff09;&#xff09;调用fit_transform&#xff08;对于文档建立分类词频矩阵&#xff0c;不能同时调用&#xff09; 把特征工程的接口称之为转换器&…

采集某新闻网资讯网站保存PDF

网址&#xff1a;融资总额近3亿美元、药明康德押注&#xff0c;这家抗衰老明星公司有何过人之处-36氪 想要抓取文章内容&#xff0c;但是找不到啊&#xff0c;可能是文字格式的问题&#xff0c;也可能文章内容进行了加密。 在元素中查看&#xff0c;window.initialState返回的就…

算法修炼之路之双指针含多道leetcode 经典题目

目录 前言 一&#xff1a;普通双指针 1.经典题目一 283移动0问题 分析 代码实现 2.经典题目二 1089复写0 分析 代码实现 二&#xff1a;解决成环类问题-快慢指针 经典例题一 202快乐数 分析 代码实现 三&#xff1a;左右相遇指针 经典例题一 11 盛最多水的容…

杂货铺 | Linux虚拟机Ubuntu操作系统下设置共享文件夹(以及找不到hgfs文件夹怎么办)

文章目录 &#x1f4da;步骤一&#xff1a;配置共享文件夹&#x1f4da;步骤二&#xff1a;配置挂载环境&#x1f4da;步骤三&#xff1a;解决权限问题&#x1f4da;步骤四&#xff1a;解决重启失效问题 &#x1f4da;步骤一&#xff1a;配置共享文件夹 建立本地共享文件夹&…

TripoSR: Fast 3D Object Reconstruction from a Single Image 论文阅读

1 Abstract TripoSR的核心是一个基于变换器的架构&#xff0c;专为单图像3D重建设计。它接受单张RGB图像作为输入&#xff0c;并输出图像中物体的3D表示。TripoSR的核心包括&#xff1a;图像编码器、图像到三平面解码器和基于三平面的神经辐射场&#xff08;NeRF&#xff09;。…

程序员做副业,AI+公众号爆文,开启赚钱新模式!

给大家介绍一个程序员可做的副业&#xff0c;AI公众号爆文项目。 公众号已经成为了一个巨大的流量池&#xff0c;许多优秀的公众号作者通过发布爆款文章&#xff0c;获得了丰厚的收益。 而作为程序员的你&#xff0c;是否也想过要利用自己的技术优势&#xff0c;在这个领域分…

React Router 5 vs 6:使用上的主要差异与升级指南

React Router 5 的一些API 在 React Router 6 上有时可能找不到&#xff0c;可能会看到如下画面&#xff1a;export ‘useHistory’ was not found in ‘react-router-dom’ … React Router目前有两个大的版本&#xff0c;即React Router 5、6。React Router 6 在设计上更加简…

自然语言处理NLP:文本预处理Text Pre-Processing

大家好&#xff0c;自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向&#xff0c;其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将介绍文本预处理的本质、原理、应用等内容&#xff0c;助力自然语言处理和模型的生成使用。 1.文本…