【设计模式 01】单例模式

单例模式,是一种创建型设计模式,他的核心思想是保证一个类只有一个实例(即,在整个应用程序中,只存在该类的一个实例对象,而不是创建多个相同类型的对象),并提供一个全局访问点来访问这个实例(即,其他类只能通过一个,可以是静态方法,来获取到这个唯一实例)。

优势:因为只有一个实例,既避免了多次创建相同的对象,节省了系统资源。多个类,也就是模块之间可以通过单例实例来共享数据;同时方便我们站在全局的角度控制唯一实例的访问(即,可以严格的控制客户怎样访问它、何时访问他);此外,单例模式还允许只在需要时才进行实例化,即所谓的懒加载,以提高程序的性能。

实现一个单例设计模式需要满足以下的基本要求首先,任何外部代码不能够随意创建实例,也就意味着类的构造函数只能私有;其次,任何外部代码也不能够随意访问实例中的任何资源,也就意味着所有的静态实例变量须是私有的;最后,需要设置一个公有的静态方法,以便外部能够获取到实例的内部资源。

单例模式的实现方式有:懒汉式(只有在遇到请求实例时才会创建一个实例,并且如果已经创建过,就会返回已有的实例)、饿汉式(类加载时就已经完成了实例的创建,不管创建的实例在后面会不会使用,先创建再说)等。

在多线程环境下,由于饿汉式在程序启动阶段就完成实例的初始化,因此不存在多个线程同时尝试初始化实例的问题;但是懒汉式中多个线程同时访问 GetInstance() 方法,并且在同一时刻检测到实例没有被创建(只要线程切换足够频繁就有可能发生),就可能会同时创建实例,从而导致多个实例被创建,(好比你和小明都发现家里每米了,在你们没有相互通知的情况下,都会去超市买一袋米,这样就重复购买了,违背了单例模式)这种情况下我们可以采用一些同步机制,例如使用互斥锁来确保在任何时刻只有一个线程能够执行实例的创建。

以下是单例设计模式的基本写法,以Java代码为例

  • 饿汉式:
public class Singleton {private static final Singleton instance = new Singleton(); // 类加载时就被创建private Singleton() {// 私有构造方法,防止外部实例化}public static Singleton getInstance() {return instance;}
} 
  • 懒汉式 + 互斥锁:
public class Singleton {private static final Singleton instance;private Singleton() {// 私有构造方法,防止外部实例化}public static synchronized Singleton getInstance() {if (instance == null) {instance == new Singleton();}return instance;}
} 
  • 懒汉式 + 双重检查锁提高性能:
public class Singleton {private static final Singleton instance;private Singleton() {// 私有构造方法,防止外部实例化}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance == new Singleton();}}}return instance;}
} 

在Java中,关键字synchronized用于实现线程的同步。

首先,synchronized可以用来修饰方法,表示该方法在同一时间只能被一个线程访问。当一个线程访问该方法时,其他线程必须等待该线程执行完毕才能访问该方法。

其次,synchronized还可以用来修饰代码块。当多个线程需要访问共享资源时,可以使用synchronized来保证同一时间只有一个线程可以访问该资源。synchronized代码块使用一个对象作为锁,当一个线程进入synchronized代码块时,会尝试获取该对象的锁,如果锁被其他线程占用,则该线程被阻塞,直到锁被释放。

synchronized的作用是避免多个线程对共享资源的并发访问导致的数据不一致或者错误。通过使用synchronized,可以保证在同一时间只有一个线程对共享资源进行访问,从而保证了线程安全。

"类.class"是Java编程中的一种语法结构,用于获取某个类的Class对象。在Java中,每个类都对应一个Class对象,该对象包含了有关类的结构、字段、方法等信息,可以在程序运行时通过反射机制来访问和操作类的成员。

通过类名后面添加".class",可以获得该类的Class对象。例如,"String.class"返回String类的Class对象,"Integer.class"返回Integer类的Class对象。

使用Class对象可以进行一些操作,比如实例化对象、访问类的静态成员、获取类的父类和接口等。

请注意,类.class只能用于获取该类的Class对象,不能用于实例化这个类的对象。要实例化一个类的对象,可以使用Class对象中的newInstance()方法或者使用构造函数来创建对象。

总结一下,我们应当什么时候使用单例设计模式:

  1. 如果多个模块都需要共享某一种资源,例如一个全局的配置管理器来存储管理配置信息、管理数据库连接池信息等,可以使用单例设计模式。
  2. 如果创建对象本身就比较消耗资源,而且可能在整个程序中都不一定会使用,就可以使用单例模式中的懒加载;
  3. 有些场景中只需要一个实例就足以协调所有行为,创建多个实例没有必要甚至会导致不好的后果,例如管理应用程序中的缓存、管理线程池。

管理应用程序中的缓存只需要一个缓存实例的原因是为了保持数据的一致性和避免冲突。

当应用程序使用多个缓存实例时,可能会导致以下问题:

  1. 数据一致性:如果多个缓存实例各自独立管理数据,那么在不同实例中的数据可能会不一致。当更新或删除数据时,如果没有及时同步所有的缓存实例,可能导致数据的不一致性,从而引发潜在的问题。

  2. 资源浪费:每个缓存实例都需要占用内存和其他资源,如果使用多个缓存实例,会造成资源的浪费。而只使用一个缓存实例可以更有效地利用资源。

  3. 缓存冲突:多个缓存实例可能会导致相同的数据被同时缓存在不同的实例中,从而造成缓存冲突。如果多个实例同时读写相同的数据,可能会引发并发问题,影响应用程序的性能和正确性。

通过只使用一个缓存实例,可以确保数据的一致性,并最大程度地节省资源。可以使用单例模式来创建和管理缓存实例,确保应用程序中只存在一个缓存对象。这样可以简化缓存管理的操作,提高系统的可靠性和性能。

【设计模式专题之单例模式】1.小明的购物车

 CPP版本:

#include <iostream>
#include <vector>
#include <map>using namespace std;class ShoppingCartManager {
public:// 获取购物车实例static ShoppingCartManager& getInstance() {static ShoppingCartManager instance;return instance;}// 添加商品到购物车void addToCart(const string& itemName, int quantity) {if (cart.find(itemName) == cart.end()) {order.push_back(itemName);}cart[itemName] += quantity;}// 查看购物车void viewCart() const {for (const auto& itemName : order) {cout << itemName << " " << cart.at(itemName) << endl; // 不能使用cart[itemName],因为处在一个const方法,不能有修改变量值的格式出现。}}private:// 私有构造函数ShoppingCartManager() {}// 购物车存储商品和数量的映射map<string, int> cart;// 记录加入购物车的顺序vector<string> order;
};int main() {string itemName;int quantity;while (cin >> itemName >> quantity) {// 获取购物车实例并添加商品ShoppingCartManager& cart = ShoppingCartManager::getInstance();cart.addToCart(itemName, quantity);}// 输出购物车内容const ShoppingCartManager& cart = ShoppingCartManager::getInstance();cart.viewCart();return 0;
}

在C++中,static关键字可以有多种作用

  1. 静态变量(Static Variables):在函数内使用static关键字,可以创建静态变量。静态变量在函数调用结束后仍然存在,并且在下一次调用函数时保持其值不变。这使得静态变量在需要记住上一次函数调用结果或在多次调用之间共享数据时非常有用。

  2. 静态成员变量(Static Member Variables):在类内部使用static关键字,可以创建静态成员变量。静态成员变量属于类本身而不是类的实例,因此在不创建类的对象时也可以访问和修改它们。静态成员变量在类的所有实例之间共享数据。

  3. 静态函数(Static Functions):在类内部使用static关键字,可以创建静态函数。静态函数不依赖于类的实例,因此可以直接通过类名调用,无需创建类的对象。静态函数主要用于处理和类本身相关的操作,而不是与类的实例数据交互。

  4. 静态类(Static Classes):在C++中,可以将类声明为static类。静态类的成员函数和成员变量都必须是静态的,而且无法创建静态类的对象。静态类主要用于实现一些全局可访问的、不需要创建对象的功能,类似于命名空间的作用。

总的来说,C++中的static关键字可以用于创建静态变量、静态成员变量、静态函数以及静态类,它们都具有特定的作用和用途。

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

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

相关文章

java012 - Java集合基础

1、集合基础 1.1 集合概述 引用数据类型包括&#xff1a;类、接口、数组[] 1.2 ArrayList构造和添加方法 代码&#xff1a; 空集合对象&#xff1a;[] add() add(int index,E element): 1.3 ArrayList集合常用方法

Stable Diffusion 模型分享:Henmix_Real(人像、真实、写真、亚洲面孔)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八下载地址模型介绍 作者述:这个模型试图改

Springboot教程(五)——单元测试

idea中一般使用JUnit进行单元测试 基本使用 我们可以在idea的test文件夹下的XXXXApplicationTests内进行单元测试&#xff1a; 可以在Test标注的方法上写测试代码&#xff1a; SpringBootTest class C0101ApplicationTests {Testfun contextLoads() {println("Hello …

基础二分学习笔记

模板 : 个人倾向第一种 ; 整数二分 : 最大化查找 : 可行区域在左侧 : 查找最后一个<q的数的下标 : int find(int q){// 查找最后一个 < q 的下标 int l 0 , r n 1 ;while(l 1 < r){int mid l r >> 1 ;if(a[mid]<q) l mid ;else r mid ;}return…

土壤类型数据

国家地球系统科学数据中心

AGM CPLD (AGRV2K )的时钟(外部时钟和片上内部振荡器)

AGM CPLD &#xff08;AGRV2K &#xff09;的时钟(外部时钟和片上内部振荡器) 外部晶振 与 内部振荡器&#xff1a; mcu 和 cpld 联合编程时&#xff0c; 整颗芯片需要一颗外部晶振。 &#xff08;芯片有内部振荡器&#xff0c; 但误差较大&#xff0c; 校准后 5%以内误差&…

Electron通过预加载脚本从渲染器访问Node.js

问题&#xff1a;如何实现输出Electron的版本号和它的依赖项到你的web页面上&#xff1f; 答案&#xff1a;在主进程通过Node的全局 process 对象访问这个信息是微不足道的。 然而&#xff0c;你不能直接在主进程中编辑DOM&#xff0c;因为它无法访问渲染器 文档 上下文。 它们…

【软考】数据库的三级模式

目录 一、概念1.1 说明1.2 数据库系统体系结构图 二、外模式三、概念模式四、内模式 一、概念 1.1 说明 1.数据的存储结构各不相同&#xff0c;但体系结构基本上具有相同的特征&#xff0c;采用三级模式和两级镜像 2.数据库系统设计员可以在视图层、逻辑层和物理层对数据进行抽…

matplotlib散点图

matplotlib散点图 假设通过爬虫你获取到了北京2016年3, 10月份每天白天的最高气温(分别位于列表a, b), 那么此时如何寻找出气温和随时间(天)变化的某种规律? from matplotlib import pyplot as pltx_3 range(1, 32) x_10 range(51, 82)y_3 [11,17,16,11,12,11,12,6,6,7,8…

试手一下CameraX(APP)

书接上回。 首先还是看谷歌的官方文档&#xff1a; https://developer.android.com/media/camera/camerax?hlzh-cn https://developer.android.com/codelabs/camerax-getting-started?hlzh-cn#1 注&#xff1a;这里大部分内容也来自谷歌文档。 官方文档用的是Kotlin&…

Day14:信息打点-主机架构蜜罐识别WAF识别端口扫描协议识别服务安全

目录 Web服务器&应用服务器差异性 WAF防火墙&安全防护&识别技术 蜜罐平台&安全防护&识别技术 思维导图 章节知识点 Web&#xff1a;语言/CMS/中间件/数据库/系统/WAF等 系统&#xff1a;操作系统/端口服务/网络环境/防火墙等 应用&#xff1a;APP对象/…

小程序图形:echarts-weixin 入门使用

去官网下载整个项目&#xff1a; https://github.com/ecomfe/echarts-for-weixin 拷贝ec-canvs文件夹到小程序里面 index.js里面的写法 import * as echarts from "../../components/ec-canvas/echarts" const app getApp(); function initChart(canvas, width, h…

Vscode 使用SSH远程连接树莓派的教程(解决卡在Downloading with wget)

配置Vscode Remote SSH 安装OpenSSH 打开Windows开始页面&#xff0c;直接进行搜索PowerShell&#xff0c;打开第一个Windows PowerShell&#xff0c;点击以管理员身份运行 输入指令 Get-WindowsCapability -Online | ? Name -like OpenSSH* 我是已经安装好了&#xff0c;…

学会玩游戏,智能究竟从何而来?

最近在读梅拉妮米歇尔《AI 3.0》第三部分第九章&#xff0c;谈到学会玩游戏&#xff0c;智能究竟从何而来&#xff1f; 作者: [美] 梅拉妮米歇尔 出版社: 四川科学技术出版社湛庐 原作名: Artificial Intelligence: A Guide for Thinking Humans 译者: 王飞跃 / 李玉珂 / 王晓…

基于springboot实现计算机类考研交流平台系统项目【项目源码+论文说明】

基于springboot实现计算机类考研交流平台系统演示 摘要 高校的大学生考研是继高校的高等教育更上一层的表现形式&#xff0c;教育的发展是我们社会的根本&#xff0c;那么信息技术的发展又是改变我们生活的重要因素&#xff0c;生活当中各种各样的场景都存在着信息技术的发展。…

Debezium发布历史163

原文地址&#xff1a; https://debezium.io/blog/2023/09/23/flink-spark-online-learning/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Online machine learning with the data streams from the database …

SpringBlade CVE-2022-27360 export-user SQL 注入漏洞分析

漏洞描述 SpringBlade是一个基于Spring Cloud和Spring Boot的开发框架&#xff0c;旨在简化和加速微服务架构的开发过程。它提供了一系列开箱即用的功能和组件&#xff0c;帮助开发人员快速构建高效可靠的微服务应用。该产品/api/blade-user/export-user接口存在SQL注入。 漏…

Java - List集合与Array数组的相互转换

一、List 转 Array 使用集合转数组的方法&#xff0c;必须使用集合的 toArray(T[] array)&#xff0c;传入的是类型完全一样的数组&#xff0c;大小就是 list.size() public static void main(String[] args) throws Exception {List<String> list new ArrayList<S…

分布式ID生成策略-雪花算法Snowflake

分布式ID生成策略-雪花算法Snowflake 一、其他分布式ID策略1.UUID2.数据库自增与优化2.1 优化1 - 共用id自增表2.2 优化2 - 分段获取id 3.Reids的incr和incrby 二、雪花算法Snowflake1.雪花算法的定义2.基础雪花算法源码解读3.并发1000测试4.如何设置机房和机器id4.雪花算法时钟…

【misc | CTF】BUUCTF 二维码

天命&#xff1a;这题使用到脚本暴力破解压缩包文件里面的密码&#xff0c;还是比较有意思的 一开始是一个二维码&#xff0c;扫码进去有一个假flag 扔进图片隐写工具&#xff0c;啥也没有&#xff0c;都是同一个二维码 使用工具&#xff1a;foremost&#xff0c;直接分离图片&…