【只生一个好 - 单例设计模式(Singleton Pattern)】

单例设计模式

  • 单例设计模式(Singleton Pattern)
    • talk is cheap, show you my code
      • 饿汉式
      • 懒汉式
      • 双重检查锁定
      • 静态内部类
      • 枚举
    • 总结

单例设计模式(Singleton Pattern)

单例设计模式(Singleton Pattern)是面向对象编程中的一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。这种模式在需要控制资源的访问或配置时非常有用,例如数据库连接池、线程池、缓存等场景。

太抽象了
来我们换个说法,当一些资源比较重的时候,我们不希望创建那么多的实例。举个现实的例子,我们有一大堆地方法院;但是最高法院只有一个。为什么? 因为当所有的事情有分歧的时候,一层层上报,总是需要有一个部门有最终决策权。

talk is cheap, show you my code

饿汉式

饿汉式是在类加载时就创建好实例,这种方式简单直接,但缺点是即使实例从未被使用过,也会占用内存资源。

public class Singleton {private static Singleton singleton = new Singleton();private Singleton() {}public static Singleton getInstance() {return singleton;}
}

我们通过将Singleton设置为private,使得外部没有办法调用构造方法新建实例;又利用类加载机制,我们将Singleton设置为静态变量,这样的话,类加载的时候,就可以新建一个实例;最后开放一个静态方法getInstance()返回实例。

懒汉式

懒汉式是在第一次调用 getInstance() 方法时才创建实例,这样可以节省资源,但是如果多线程环境下未加锁可能会导致多个实例被创建。

public class Singleton1 {private static Singleton1 singleton = null;private Singleton1() {}public static Singleton1 getInstance() {if (singleton == null) {singleton = new Singleton1();}return singleton;}
}

我们通过将Singleton设置为private,使得外部没有办法调用构造方法新建实例;然后调用getInstance()的时候触发新建实例的动作,返回实例,但是这个代码在多线程下可能会创建出多个实例。

双重检查锁定

上面的懒汉式单例写入有多线程的安全问题,为了保证线程安全同时避免不必要的同步开销,可以采用双重检查锁定的方式。

public class Singleton1 {private volatile static Singleton1 singleton = null;private Singleton1() {}public static Singleton1 getInstance() {if (singleton == null) {synchronized (Singleton1.class) {if (singleton == null) {singleton = new Singleton1();}}}return singleton;}
}

synchronized这个关键字用来加锁,但是仅仅通过synchronized也不能保证只产生一个实例,为什么呢?
因为第一个 if (singleton == null)后面通过synchronized拿锁,然后有一个线程会拿到锁,另一些在等待锁,如果不写第二个if判断的话,导致第一个拿到锁的执行了创建实例的操作,释放锁。而等待锁的线程就可以拿到锁,导致又创建了新的实例,所以我们要写两个if判断。所以这种创建单例的写法又叫做双重检查锁定。

静态内部类

public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

利用 Java 的类加载机制,在第一次调用 getInstance() 方法时才会加载静态内部类,从而实现延迟初始化和线程安全。换言之,这种的线程安全是通过类加载机制保证的,我们就不需要再写线程安全控制了。
另外补充private static final Singleton INSTANCE = new Singleton();这个看起来像是饿汉式,但是实际上只有调用getInstance的时候才会创建对象,因为SingletonHolder是在它自己被调用的时候才会触发类加载。所以从创建时机上看,这种是懒汉式一样的。

枚举

枚举天生就是线程安全的,并且可以防止反序列化攻击,因此它是一种非常简洁且推荐的方式来实现单例模式。

public enum Singleton {INSTANCE;// 单例对象的成员变量private String data;// 私有构造函数private Singleton() {this.data = "Initial Data";}// 获取数据的方法public String getData() {return data;}// 设置数据的方法public void setData(String data) {this.data = data;}// 其他方法public void doSomething() {System.out.println("Doing something with data: " + data);}// 主方法用于测试public static void main(String[] args) {// 获取单例实例Singleton singleton = Singleton.INSTANCE;// 使用单例实例的方法System.out.println(singleton.getData()); // 输出: Initial Datasingleton.setData("New Data");System.out.println(singleton.getData()); // 输出: New Datasingleton.doSomething(); // 输出: Doing something with data: New Data}
}

总结

单例模式特点:

  1. 单例模式的优点
  • 唯一性:确保了类在整个应用程序中只有一个实例。
  • 控制资源:对于需要严格控制资源使用的场合非常适合。
  • 延迟加载:可以通过某些实现方式(如懒汉式、静态内部类)实现延迟初始化,节省资源。
  • 线程安全:通过适当的实现方式可以保证在多线程环境下的安全性。
  1. 单例模式的缺点
  • 难以测试:单例模式引入了全局状态,这可能使得单元测试变得困难。
  • 隐藏依赖关系:因为单例模式通常通过静态方法提供实例,所以依赖关系往往被隐藏起来,不利于依赖注入和代码维护。
  • 不适用于分布式系统:在一个分布式的环境中,单例模式无法保证跨进程或跨机器的唯一性。

单例模式应用场景

  • 配置管理:如读取配置文件或环境变量。
  • 日志记录器:整个应用共享同一个日志记录器实例。
  • 工厂类:如工厂模式中的工厂类,确保所有客户端都使用同一个工厂来创建对象。
  • 数据库连接池:控制对数据库连接的访问,确保高效利用有限的连接资源。

单例模式是一个简单而强大的设计模式,广泛应用于各种需要确保唯一实例的场景。Spring 中的Bean默认就是单例模式的。

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

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

相关文章

大模型的实践应用33-关于大模型中的Qwen2与Llama3具体架构的差异全解析

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用33-关于大模型中的Qwen2与Llama3具体架构的差异全解析。Qwen2模型与Llama3模型在架构上存在一些细微的差异,这些差异主要体现在注意力机制、模型尺寸相关参数以及嵌入层处理等方面。以下是对这些差异的详细分析。 文章…

NAT 技术如何解决 IP 地址短缺问题?

NAT 技术如何解决 IP 地址短缺问题? 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 随着互联网的普及和发展,IP 地址的需求量迅速增加。尤其是 IPv4 地址&…

kafka的备份策略:从备份到恢复

文章目录 一、全量备份二、增量备份三、全量恢复四、增量恢复 前言:Kafka的备份的单元是partition,也就是每个partition都都会有leader partiton和follow partiton。其中leader partition是用来进行和producer进行写交互,follow从leader副本进…

使用sam进行零样本、零学习的分割实践

参照:利用SAM实现自动标注_sam标注-CSDN博客,以及SAM(分割一切模型)的简单调用_sam使用-CSDN博客 sam简介: Segment Anything Model(SAM)是Meta公司于2023年发布的一种AI模型,它打破…

【Git】—— 使用git操作远程仓库(gitee)

目录 一、远程仓库常用命令 1、从远程仓库克隆项目 2、查看关联的远程仓库 3、添加关联的远程仓库 4、移除关联的远程仓库 5、将本地仓库推送到远程仓库 6、从远程仓库拉取项目 二、分支命令 1、查询分支 2、创建分支 3、切换分支 4、推送到远程分支 5、合并分支 …

攻防世界web新手第五题supersqli

这是题目,题目看起来像是sql注入的题,先试一下最常规的,输入1,回显正常 输入1‘,显示错误 尝试加上注释符号#或者–或者%23(注释掉后面语句,使1后面的单引号与前面的单引号成功匹配就不会报错…

【MySQL】SQL 优化经验

1. 表的设计优化 参考依据:参考阿里开发手册嵩山版,其中有很多关于MySQL表设计的内容。类型选择:根据存储内容选择合适类型,如数值存储可选tinyint、bigint等,字符串可选varchar或text,根据内容长短选择合…

使用 .NET 6 或 .NET 8 上传大文件

如果您正在使用 .NET 6,并且它拒绝上传大文件,那么本文适合您。 我分享了一些处理大文件时需要牢记的建议,以及如何根据我们的需求配置我们的服务,并提供无限制的服务。 本文与 https://blog.csdn.net/hefeng_aspnet/arti…

STM32使用UART发送字符串与printf输出重定向

首先我们先看STM32F103C8T6的电路图 由图可知,其PA9和PA10引脚分别为UART的TX和RX(注意:这个电路图是错误的,应该是PA9是X而PA9是RX,我们看下图的官方文件可以看出),那么接下来我们应该找到该引脚的定义是什么&#xf…

转运机器人推动制造业智能化转型升级

​在当今制造业智能化转型的浪潮中,技术创新成为企业脱颖而出的关键。富唯转运机器人凭借一系列先进技术,成为智能转型的卓越之选。 一体化 AMR 控制系统是富唯的一大亮点。它采用低代码流程搭建和配置模式,极大地缩短了部署时间。企业无需耗…

深度分析java 使用 proguard 如何解析混淆后的堆栈

经过proguard混淆过后,发生异常时堆栈也进行了混淆,那么如果获取的原始的堆栈呢?我们下面来看下 使用proguard 根据mapping文件直接解析 import proguard.obfuscate.MappingReader; import proguard.retrace.FrameInfo; import proguard.re…

基于JAVA+SpringBoot+Vue的影院订票系统

基于JAVASpringBootVue的影院订票系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接🍅 哈喽兄…

LeetCode 83 :删除排链表中的重复元素

题目: 地址:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 方法一: 方法二: package com.zy.leetcode.LeetCode_04;/*** Author: zy* Date: 2024-12-25-15:19* Description: 删除排链表中的里复元素* …

金仓数据库-用户与角色对象权限访问的查看

数据库用户 创建用户 创建用户且设置密码 create user user01 password 123;\du 查看用户user01,可以看见创建成功 创建用户设置密码和不可继承 create user02 password 123 noinherit;修改用户的属性 设置用户的连接数 设置为1个 alter user user01 connect…

理解神经网络

神经网络是一种模拟人类大脑工作方式的计算模型,是深度学习和机器学习领域的基础。 基本原理 神经网络的基本原理是模拟人脑神经系统的功能,通过多个节点(也叫神经元)的连接和计算,实现非线性模型的组合和输出。每个…

联通光猫怎么自己改桥接模式?

环境: 联通光猫 ZXHN F677V9 硬件版本号 V9.0 软件版本号 V9.0.0P1T3 问题描述: 联通光猫怎么自己改桥接模式 家里用的是ZXHN F677V9 光猫,最近又搞了个软路由,想改桥接模式 解决方案: 1.拿到最新超级密码&…

Matrix-Breakout 2 Morpheus(找到第一个flag)

第一步 信息收集 (1)寻找靶场真实ip arp-scan -l 靶场真实 ip 为192.168.152.154 (2)探测端口及服务 nmap -p- -sV 192.168.52.135 第二步 开始渗透 (1)访问web服务 http://192.168.152.154and http://192.168.52.135:81 发现 81 端口的页面要登录 我们使用 dirb 扫描…

【CSS in Depth 2 精译_094】16.2:CSS 变换在动效中的应用(下)——导航菜单的文本标签“飞入”特效与交错渲染效果的实现

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…

机器人C++开源库The Robotics Library (RL)使用手册(三)

进入VS工程,我们先看看这些功能函数及其依赖库的分布关系: rl命名空间下,主要有八大模块。 搞定VS后将逐个拆解。 1、编译运行 根据报错提示,配置相应错误的库(根据每个人安装位置不同而不同,我的路径如下:) 编译所有,Release版本耗时大约10分钟。 以rlPlan运动…