设计模式--单例模式(Singleton Pattern)
一、什么是单例模式
单例模式是一种创建型设计模式,它旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式限制了类的实例化次数为一个,并提供一种在应用程序中共享一个实例的方式。这对于需要只有一个实例来管理某些资源或状态的情况非常有用。
单例模式通常涉及以下几个核心概念:
- 私有构造函数(Private Constructor):单例类的构造函数被声明为私有,这意味着外部无法直接通过构造函数来创建类的实例。
- 静态成员变量(Static Member Variable):单例类通常会包含一个静态成员变量,用于保存唯一的实例。
- 静态成员函数(Static Member Function):通过静态成员函数来获取单例实例。这个函数通常负责检查是否已经有实例存在,如果没有则创建一个新的实例,并返回该实例。
通过实现单例模式,可以确保在应用程序中只有一个全局的实例,这对于资源共享、状态管理、配置信息等情况非常有用。然而,需要注意在多线程环境下实现单例模式可能会带来线程安全的问题,因此需要采取适当的措施来确保线程安全性。
二、单例模式代码样例
当实现单例模式时,我们需要确保类只有一个实例,并且提供全局访问点来获取该实例。以下是一个用C++实现的简单单例模式的代码样例:
#include <iostream>class Singleton {
private:static Singleton* instance; // 静态成员变量,保存唯一实例Singleton() {// 私有构造函数,防止外部实例化std::cout << "Singleton instance created." << std::endl;}public:// 静态成员函数,获取单例实例static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Singleton is doing something." << std::endl;}
};Singleton* Singleton::instance = nullptr; // 初始化静态成员变量int main() {Singleton* singleton1 = Singleton::getInstance();Singleton* singleton2 = Singleton::getInstance();if (singleton1 == singleton2) {std::cout << "singleton1 and singleton2 are the same instance." << std::endl;}singleton1->doSomething();return 0;
}
在这个例子中,Singleton 类有一个私有的静态成员变量 instance 用于保存唯一实例。构造函数是私有的,这样外部无法实例化。通过静态成员函数 getInstance 来获取单例实例,如果实例不存在,则创建一个新实例。其他成员函数可以在实例上执行操作。
需要注意的是,这种简单的实现在多线程环境下可能会出现问题,因为在并发情况下可能会创建多个实例。为了确保线程安全,可以使用互斥锁或者其他同步机制。
当在单例模式中面临多线程环境时,需要确保线程安全。以下是一个使用互斥锁(mutex)来实现线程安全的单例模式样例:
#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mutex; // 互斥锁Singleton() {std::cout << "Singleton instance created." << std::endl;}public:static Singleton* getInstance() {std::lock_guard<std::mutex> lock(mutex); // 在获取实例时加锁if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Singleton is doing something." << std::endl;}
};Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex; // 初始化互斥锁int main() {Singleton* singleton1 = Singleton::getInstance();Singleton* singleton2 = Singleton::getInstance();if (singleton1 == singleton2) {std::cout << "singleton1 and singleton2 are the same instance." << std::endl;}singleton1->doSomething();return 0;
}
三、使用单例模式需要注意的问题
使用单例模式时需要注意以下几点:
- 线程安全性:如果在多线程环境中使用单例模式,确保实现线程安全,以防止多个线程同时创建实例。可以使用互斥锁、双检锁等方法来保证线程安全。
- 延迟实例化:单例模式通常在第一次使用时创建实例。如果实例化过早,可能会造成资源浪费。只有在需要时才创建实例,这种延迟实例化的方式可以提高性能和效率。
- 内存泄漏:由于单例模式的实例在整个应用程序生命周期内存在,如果不适当地管理实例,可能会导致内存泄漏。在程序结束时,应该正确地销毁实例。
- 全局状态:由于单例模式提供了全局访问点,可能导致过度使用全局状态。过多地使用全局状态可能会导致代码难以维护,因此应该谨慎使用单例模式。
- 单一职责原则:尽量确保单例类只负责管理单一的实例,而不应该涉及过多的业务逻辑。将不同的功能拆分到不同的类中,以遵循单一职责原则。
- 反射和序列化:一些编程语言和环境支持反射和序列化,这可能会破坏单例模式。为了避免这种情况,可以通过禁用类的克隆、序列化等方式来保护单例的独特性。
- 测试难度:由于单例模式的全局状态,可能会导致测试变得困难,因为在不同的测试用例之间共享状态可能会产生副作用。为了更好地进行单元测试,可以使用依赖注入等技术。
总之,单例模式在适当的情况下是非常有用的,但也需要谨慎使用,以避免潜在的问题和复杂性。了解单例模式的优缺点,并根据具体情况来决定是否使用它。

相关文章:
设计模式--单例模式(Singleton Pattern)
一、什么是单例模式 单例模式是一种创建型设计模式,它旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式限制了类的实例化次数为一个,并提供一种在应用程序中共享一个实例的方式。这对于需要只有…...
postgis数据库从一张表中过滤出一部分数据到新表中
你可以使用以下步骤在PostGIS数据库中过滤objectid<100的数据,并将其创建为新表:打开PostGIS数据库的终端或客户端工具(如Psql)。 选择你要过滤数据的表。假设表名为"original_table",该表包含一个名为&q…...
INDEMIND:“大+小”多机协同,实现机器人商用场景全覆盖
随着商用清洁机器人进入越来越多的场景中,单一的中型机器人并不能有效覆盖所有区域,更加细分化的产品组合正在成为新的趋势。 产品形态的“新趋势” 在商用场景中,目前的商用清洁机器人几乎均是中大型的产品形态,较大的体型意味…...
微信开发之一键创建标签的技术实现
简要描述: 添加标签 请求URL: http://域名地址/addContactLabel 请求方式: POST 请求头Headers: Content-Type:application/jsonAuthorization:login接口返回 参数: 参数名必选类型说明…...
八一参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022.
八一参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022....
ChatGPT⼊门到精通(7):GPT3.5与 4.0区别
⼀、详细区别 1 项⽬ GPT3.5 GPT4.0 2 打字速度 较慢,⾼峰期更慢 更加慢,差别不⼤ 3 掉线⼏率 经常掉线 很少掉线 4 分段能⼒ ⽣成⼏百字后就停⽌了, 需要回复“继续”,有时候不 是很连贯 基本连贯 5 使⽤限制 1⼩时100次提问&am…...
Springboot整合MyBatisPlus框架操作MySQL
1、MyBatis-Plus概述 MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 【技术储备】 拥有 Java 开发环境以及相应 IDE…...
基于Jenkins构建生产CICD环境(第二篇)
基于Jenkins自动打包并部署Tomcat环境 传统网站部署的流程 在运维过程中,网站部署是运维的工作之一。传统的网站部署的流程大致分为:需求分 析-->原型设计-->开发代码-->提交代码-->内网部署-->内网测试-->确认上线-->备份数据-->外网更新…...
ioctl、printk及多个此设备支持
一、ioctl操作实现 ioctl(Input/Output Control)是一个在 Unix-like 操作系统中的系统调用,用于控制设备或文件的各种操作。它允许用户空间程序与内核空间进行交互,执行一些特定的设备控制、状态查询或其他操作,而不必…...
电脑每次开机杀毒软件报iusb3mon.exe病毒已清除,电脑中病毒iusbmon杀毒办法,工具杀毒
不知道什么时候开始,我电脑C盘的系统数据存储文件夹programdata 不知不觉就没了,找不到了 programdata文件夹为存储系统数据文件的,这个文件不见了,而且我打开了显示隐藏文件和文件夹还是没有显示 然后我重启电脑,杀毒…...
centos服务器系统下安装python3并与自带的python2
centos服务器系统下安装python3并与自带的python2 在centos中,自带有python2,因此需要经常安装python3。但是这里有一个坑,就是centos的yum是用python2写的,如果正常编译安装python3,那么yum就会直接挂了。为了方便以…...
(二十)大数据实战——Flume数据采集的基本案例实战
前言 本节内容我们主要介绍几个Flume数据采集的基本案例,包括监控端口数据、实时监控单个追加文件、实时监控目录下多个新文件、实时监控目录下的多个追加文件等案例。完成flume数据监控的基本使用。 正文 监控端口数据 ①需求说明 - 使用 Flume 监听一个端口&am…...
AutoCAD图如何保存为Word
AutoCAD图如何保存为Word 引言AutoCAD图保存为Word文件步骤: 引言 不知道大家有没有是否遇到需要将AutoCAD图保存到Word中。有些小伙伴可能直接截图插入Word中,这种方法简单,但对于有高清图片需求的小伙伴就不适用了。接下来我就为大家介绍一…...
Java线程 - 详解(2)
一,线程安全问题 有些代码在单个线程的环境下运行,完全正确,但是同样的代码,让多个线程去执行,此时就可能出现BUG,这就是所谓的 "线程安全问题"。举一个例子: public class Demo {s…...
事务特性 - 达梦数据库
达梦数据库事务特性 1 事务特性1.1 原子性1.2 一致性1.3 隔离性1.4 持久性 1 事务特性 事务必须具备什么属性才是一个有效的事务呢?一个逻辑工作单元必须表现出四种属性,即原子性、一致性、隔离性和持久性,这样才能成为一个有效的事务。DM 数…...
axios 使用FormData格式发送GET请求
如果你需要使用,FormData格式,发送GET请求 将参数拼接到 FormData对象 中,使用 URLSearchParams 将FormData对象转换为查询参数字符串,并将其拼接到URL中,这样就能以FormData格式发送GET请求给服务器 注意࿱…...
CS144(2023 Spring)Lab 1: stitching substrings into a byte stream
文章目录 前言其他笔记相关链接 1. Getting started2. Putting substrings in sequence2.1 需求分析2.2 注意事项2.3 代码实现 3. 测试与优化 前言 这一个Lab主要是实现一个TCP receiver的字符串接收重组部分。 其他笔记 Lab 0: networking warmup Lab 1: stitching substri…...
【PHP】常用的PHP内置函数
1、PHP内置函数非常丰富,用于执行各种任务。以下是一些常用的PHP内置函数: 字符串操作函数: strlen(): 返回字符串的长度。 strpos(): 查找字符串中的某个子串第一次出现的位置。 substr(): 返回字符串的子串。 str_replace(): 替换字符串中的…...
css自学框架之消息弹框
首先我们还是看看消息弹框效果: 主要实现代码分为三部分 一、CSS部分,这部分主要是定义样式,也就是我们看到的外表,主要代码: /* - 弹窗 */notice{top: 0;left: 0;right: 0;z-index: 10;padding: 1em;position: fix…...
42、Flink 的table api与sql之Hive Catalog
Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
