探索单例模式:设计模式中的瑰宝
文章目录
- 常用的设计模式有以下几种:
- 一.创建型模式(Creational Patterns):
- 二.结构型模式(Structural Patterns):
- 三.行为型模式(Behavioral Patterns):
- 四.并发模式(Concurrent Patterns):
- 单例模式概念
- 一、懒汉式(Lazy Initialization)示例:
- 二、饿汉式(Eager Initialization)示例:
- 三、静态内部类示例(推荐使用):
- 四、枚举示例(推荐使用):
- 总结
常用的设计模式有以下几种:
一.创建型模式(Creational Patterns):
工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
原型模式(Prototype Pattern)
建造者模式(Builder Pattern)
二.结构型模式(Structural Patterns):
适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
装饰器模式(Decorator Pattern)
组合模式(Composite Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
三.行为型模式(Behavioral Patterns):
策略模式(Strategy Pattern)
观察者模式(Observer Pattern)
迭代器模式(Iterator Pattern)
命令模式(Command Pattern)
模板方法模式(Template Method Pattern)
职责链模式(Chain of Responsibility Pattern)
状态模式(State Pattern)
访问者模式(Visitor Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
解释器模式(Interpreter Pattern)
四.并发模式(Concurrent Patterns):
单例模式(Singleton Pattern,在多线程环境下的应用)
生成器模式(Builder Pattern,在多线程环境下的应用)
保护性暂停模式(Guarded Suspension Pattern)
观察者模式(Observer Pattern,在多线程环境下的应用)
这些设计模式涵盖了对象的创建、对象间的组织和交互、以及对象的行为等方面,可以帮助开发者更好地组织和设计代码,提高代码的可扩展性、可维护性以及重用性。需要根据实际情况选择适合的设计模式来解决问题。
单例模式概念
单例模式是设计模式中的一种,旨在确保一个类只有一个实例对象,并提供全局访问点来获取该实例。
单例模式的关键要点如下😊😊😊:
1.私有构造函数:为了防止外部直接创建实例,将类的构造函数设为私有。
2.静态方法或静态变量:提供一个静态方法或静态变量来获取类的唯一实例。
3.延迟实例化或饿汉式初始化:根据需要可以选择延迟实例化或在类加载时就进行初始化。
4.线程安全性:需考虑在多线程环境下保证单例对象的创建和访问的线程安全性。
5.全局访问点:提供一个全局访问点,使得任何地方都可以获取到单例实例。
同时,单例模式也有一些注意点,如可能引起全局状态的问题、对单元测试的影响等,需要权衡利弊来选择适合的使用场景。😎😎😎
单例模式有以下几种常见的实现方法:😊😊😊
1.懒汉式(Lazy Initialization):
在第一次使用时才创建实例。
线程不安全,需要考虑多线程环境下的同步问题。
可以通过双重检查锁定、同步方法等方式来实现线程安全。
2.饿汉式(Eager Initialization):
在类加载时就创建实例。
线程安全,因为实例在类加载时就已经创建。
可能会导致不必要的资源浪费,因为实例在整个程序运行期间都存在,即使不使用也会被创建。
3.静态内部类:
使用静态内部类来持有单例实例,在第一次使用时才创建实例。
线程安全,因为静态内部类在类加载时只会被加载一次,保证了实例的唯一性。
推荐使用这种方式实现单例,因为代码简洁、线程安全,且支持懒加载。
4.枚举:
枚举常量就是单例对象的实例。
线程安全,且支持序列化和反序列化,以及防止反射攻击。
推荐使用这种方式实现单例,因为代码简洁、线程安全,且具有额外的优势。
一、懒汉式(Lazy Initialization)示例:
以下是一个懒汉式实现单例模式的示例(非线程安全版本):
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {// 私有的构造函数,防止外部实例化}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 其他方法...
}
在这个示例中,LazySingleton类的构造函数是私有的,不允许外部直接实例化对象。getInstance()方法是懒汉式的获取单例实例的方法。在第一次调用getInstance()时,会创建一个新的实例对象并将其赋值给instance变量。之后的调用都会返回之前创建的实例对象。
需要注意的是,这个示例是非线程安全的版本,多线程环境下可能会出现竞态条件。如果多个线程同时调用getInstance()方法,并且instance还没有被初始化,那么可能会创建多个实例。为了解决这个问题,可以使用同步机制(如双重检查锁定)来确保线程安全性。
下面是一个线程安全的双重检查锁定的示例:
public class LazySingleton {private static volatile LazySingleton instance;private LazySingleton() {// 私有的构造函数,防止外部实例化}public static LazySingleton getInstance() {if (instance == null) {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();}}}return instance;}// 其他方法...
}
在这个示例中,使用了双重检查锁定来确保线程安全。通过在synchronized块内进行二次判断,可以在多线程环境下保证只有一个实例被创建。
需要注意的是,上述示例虽然解决了线程安全性问题,但在某些情况下(如高并发场景)性能可能会有一定的影响。因此,在实际使用中可以根据需求权衡利弊来选择合适的实现方式。
二、饿汉式(Eager Initialization)示例:
以下是一个饿汉式实现单例模式的示例:
public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() {// 私有的构造函数,防止外部实例化}public static EagerSingleton getInstance() {return instance;}// 其他方法...
}
在这个示例中,EagerSingleton类在类加载时就创建了一个实例对象,并将其赋值给静态final的instance变量。getInstance()方法直接返回该实例,因此在任何时候调用getInstance()都会获取到同一个实例对象。
饿汉式的实现方式是在类加载时就进行实例化,因此可以保证线程安全性。由于实例在整个程序运行期间都会存在,可能会导致不必要的资源浪费。另外,需要注意的是,在某些特殊情况下可能会引起类加载的顺序问题,需要注意类加载的先后顺序。
总结来说,饿汉式是一种简单、线程安全的单例模式实现方式,适用于实例始终需要被创建且资源消耗较小的情况。但需要注意在某些特殊情况下可能引发的顺序问题。
三、静态内部类示例(推荐使用):
public class Singleton {private Singleton() {// 私有的构造函数,防止外部实例化}private static class SingletonHolder {private static final Singleton instance = new Singleton();}public static Singleton getInstance() {return SingletonHolder.instance;}// 其他方法...
}
在这个示例中,Singleton类的实例被定义为私有的静态内部类SingletonHolder的静态成员变量。通过使用静态内部类的方式,可以实现懒加载和线程安全,而无需使用显式的同步机制。
四、枚举示例(推荐使用):
使用枚举实现单例具有以下优点:
线程安全:枚举常量的创建是线程安全的,不会被多个线程重复创建。
防止序列化和反射攻击:枚举类默认实现了Serializable接口,使用枚举实现的单例对象在序列化和反序列化时会得到正确的结果。同时,由于枚举常量有固定的实例,不会受到反射攻击。
以下是使用枚举实现单例的示例:
public enum Singleton {INSTANCE;public void doSomething() {// 单例对象的方法}
}
在这个示例中,Singleton是一个枚举类型,并且定义了一个名为INSTANCE的枚举常量,它是单例对象的唯一实例。可以通过Singleton.INSTANCE来访问这个单例对象,并调用其方法。
使用枚举实现单例模式简洁且安全,不需要担心线程安全和反射攻击的问题。因此,当需要实现单例时,可以优先考虑使用枚举来实现。
总结
单例模式的应用有很多,例如全局资源管理、日志记录器、数据库连接池、配置管理器等。
它可以简化代码,提高资源的利用效率,并确保全局只有一个实例对象。😎😎😎
@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!
相关文章:

探索单例模式:设计模式中的瑰宝
文章目录 常用的设计模式有以下几种:一.创建型模式(Creational Patterns):二.结构型模式(Structural Patterns):三.行为型模式(Behavioral Patterns):四.并发…...
Bobo String Construction 2023牛客暑期多校训练营4-A
登录—专业IT笔试面试备考平台_牛客网 题目大意:给出一字符串t,求一个长为n的字符串,使tst中包含且仅包含两个t 1<n<1000;测试样例组数<1000 思路:一开始很容易想到如果t里有1,s就全0,否则s就全…...
【React学习】React父子组件通讯
1. 父到子传值 在React框架中,父组件可以通过 props 将数据传递给子组件。子组件通过读取 props 来访问父组件传递过来的数据。 当父组件的 props 发生变化时,React 会自动重新渲染子组件以确保子组件中使用的数据保持同步。 父组件 import React, {…...

NASM汇编
1. 前置知识 1. 汇编语言两种风格 intel:我们学的NASM就属于Intel风格AT&T:GCC后端工具默认使用这种风格,当然我们也可以加选项改成intel风格 2. 代码 1. 段分布 .text: 存放的是二进制机器码,只读.data: 存放有初始化的…...

第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面
文章目录 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面使用 HL7 架构结构页面查看文档类型列表查看消息结构查看段结构 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面 使用 HL7 架构结构页面 通过 HL7 架构页面,可以导入和查看 HL7 版本 2 架构规范。…...
spring注解驱动开发(一)
1、需要导入的spring框架的依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version></dependency>2、Configuration 设置类为配置类 3、Annota…...

Vue3搭建启动
Vue3搭建&启动 一、创建项目二、启动项目三、配置项目1、添加编辑器配置文件2、配置别名3、处理sass/scss4、处理tsx(不用的话可以不处理) 四、添加Eslint 一、创建项目 npm create vite 1.project-name 输入项目名vue3-vite 2.select a framework 选择框架 3.select a var…...
阻塞队列(模拟实现)
概念 阻塞队列是带有阻塞功能的队列 特性 当队列满的时候,继续入队列,就会出现阻塞,阻塞到其他线程从队列中取走元素为止 当队列空的时候,继续出队列,也会发生阻塞,阻塞到其他线程往队列中添加元素为止 特…...

VScode中python的相对路径与绝对路径 FileNotFoundError: [Errno 2] No such file or directory
VScode中,python里的相对路径是相对于当前工作目录来定位的,而当前的工作目录在VScode中下方的终端窗口会有提示: 说明此时的工作目录并非当前python文件所在的目录,而是C:\Users\xxxxx(你的用户名)。因此,使用VScode…...
Unity XML2——C#读写XML
一、XML 文件的存放位置 (一)只读不写的 XML 放在 Resouces 或者 StreamingAssets 文件夹下,详见 Unity基础3——Resources资源动态加载_weixin_53163894的博客-CSDN博客。 (二)动态存储的 XML 放在 Applica…...

带wiringPi库的交叉编译 ---宿主机x86Ubuntu,目标机ARMv8 aarch64(香橙派)
带wiringPi库的交叉编译如何进行 先交叉编译wiringPi库,编译出的库适合香橙派,这时候交叉编译可执行程序的平台和链接库的格式也是正确的,然后通过-I和-L来指定链接的wiringPi库的头文件和库的位置,但是现在还没有学习过…...
数据仓库基础知识
什么是数据仓库? 数仓,DataWarehouse,是一个 面向主题的、集成的、稳定的、与时间相关的 数据集合。 而这个数据集合的建立,是为了支持管理者的决策过程。 也就是说,我们通过建设数仓,为业务中的流程改进、…...

M 芯片的 macos 系统安装虚拟机 centos7 网络配置
centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了,如果重启网卡不管用,则重启虚拟机即可 “ ifcfg-ens160 ” 这…...

AcWing 3708. 求矩阵的鞍点
输入样例: 3 4 1 2 3 4 1 2 3 4 1 2 3 4输出样例: 1 4 4 2 4 4 3 4 4 #include<bits/stdc.h> using namespace std; const int N1010; int n,m,a[N][N],x[N],y[N],flag1; int main(){scanf("%d%d",&n,&m);for(int i1;i<n;i…...

web前端开发工程师的具体职责范本(合集)
web前端开发工程师的具体职责范本1 职责: 1.负责web前端架构的搭建,核心业务功能开发和核心代码编写。 2.配合产品经理,实现产品UI和交互方面的需求,持续界面优化,提升用户体验。 3.参与相关业务需求变更评审。 4.…...

从源程序到可执行文件的四个过程
从源程序到可执行文件的四个过程 预处理编译汇编链接 程序要运行起来,必须要经过四个步骤:预处理、编译、汇编和链接,如下图所示: -E选项:提示编译器执行完预处理就停下来,后边的编译、汇编、链接就先不执…...

C++部署学习
gcc -E src/main.c -o src/main.i gcc -S src/main.c -o src/main.s gcc -C src/main.c -o src/main.o gcc src/main.c -o exec ./exec...
linux下lazarus开发ide里 BGRAControls控件库comboBox示例
下载开发工具 ftp://ftp.freepascal.org/pub/lazarus/releases/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/https://sourceforge.net/projects/lazarus/files/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/ sourceforge下载可能比较慢,选择 下载有问题&…...
Redis学习路线(9)—— Redis的场景使用
默认做好了其它的前提,只专注于Redis使用 一、短信登录 在没有Redis数据库时,我们会基于Session实现登录(利用令牌进行授权),是怎么实现的呢? (一)基于Session的短信登录功能 1、…...

糟了,数据库主从延迟了!
前言 在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面 因此,一般来说都是通过集群主从复制(Master-Slave)的方式来同步数据&…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...