当前位置: 首页 > news >正文

Java23种设计模式之【单例模式】

目录

一.单例模式的起源,和应用场景

1.单例模式的前世今生!

 2.什么是单例模式?

2.1使用单例模式的注意事项

2.2如何理解单例模式?

2.3单例模式的优势以及不足!

2.4使用场景

二.实现

1.实现思路

1.1创建一个 Singleton 类 (SingleObject.java)

1.2从 singleton 类获取唯一的对象 (SingletonPatternDemo.java)

1.3控制台打印输出结果

2.单例模式的几种实现方式

2.1懒汉式,线程不安全(只有只一个不支持多线程)

2.2懒汉式,线程安全

3、饿汉式

4、双检锁/双重校验锁(DCL,即 double-checked locking)

5、登记式/静态内部类

6、枚举

7.总结

三.今天的分享就到这里,如果可以的话可以给小编点一个👍


前言:

为什么要去介绍这种模式,为什么要使用?

很简单,帮助开发人员解决常见的软件设计问题,并提供一种可重用和可扩展的解决方案!

使用的目的很简单就是解决在普通开发解决不了的问题!

一.单例模式的起源,和应用场景

1.单例模式的前世今生!

单例模式的起源可以追溯到上世纪60年代的软件工程领域。最早提出单例模式概念的是美国计算机科学家 Douglas Schmidt 和 Robert Hanmer。

在设计模式的经典著作《Design Patterns: Elements of Reusable Object-Oriented Software》中,由四位软件工程师 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides(被称为GoF 四人组)首次将单例模式正式定义为一种常用的设计模式,并描述了其用途和实现方式。

然而,单例模式的思想在实际软件开发中早就存在并且被广泛应用。例如,早期的操作系统中就有诸如"System Manager"或"Window Manager"等全局唯一的对象,这些对象的作用类似于单例模式。

因此,单例模式的起源可以说是从早期开发者在实践中总结出的一种常用的设计原则,通过确保只有一个实例存在来提供全局访问点,并在实践中得到了系统架构和软件设计的普遍应用。

 2.什么是单例模式?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。

2.1使用单例模式的注意事项

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

2.2如何理解单例模式?

  • 一个班级只有一个班主任。
  • Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
  • 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

2.3单例模式的优势以及不足!

优点:

  • 1.在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
  • 2.避免对资源的多重占用(比如写文件操作)。 

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

2.4使用场景

  • 1.要求生产唯一序列号。
  • 2.WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3.创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

二.实现

1.实现思路

1.1创建一个 Singleton 类 (SingleObject.java)

public class SingleObject {//创建 SingleObject 的一个对象private static SingleObject instance = new SingleObject();//让构造函数为 private,这样该类就不会被实例化private SingleObject(){}//获取唯一可用的对象public static SingleObject getInstance(){return instance;}public void showMessage(){System.out.println("Hello World!");}
}

1.2从 singleton 类获取唯一的对象 (SingletonPatternDemo.java)

public class SingletonPatternDemo {public static void main(String[] args) {//不合法的构造函数//编译时错误:构造函数 SingleObject() 是不可见的//SingleObject object = new SingleObject();//获取唯一可用的对象SingleObject object = SingleObject.getInstance();//显示消息object.showMessage();}
}

1.3控制台打印输出结果

执行程序,输出结果:

Hello World!

2.单例模式的几种实现方式

2.1懒汉式,线程不安全(只有只一个不支持多线程)

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

public class Singleton {  private static Singleton instance;  private Singleton (){}  public static Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  
}

2.2懒汉式,线程安全

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁
)。

public class Singleton {  private static Singleton instance;  private Singleton (){}  public static synchronized Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  
}

3、饿汉式

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式比较常用,但容易产生垃圾对象
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。

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

4、双检锁/双重校验锁(DCL,即 double-checked locking)

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:较复杂

描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
getInstance() 的性能对应用程序很关键。

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

5、登记式/静态内部类

是否 Lazy 初始化:

是否多线程安全:

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟第 3 种方式不同的是:第 3 种方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合理。

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

6、枚举

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
不能通过 reflection attack 来调用私有构造方法。

public enum Singleton {  INSTANCE;  public void whateverMethod() {  }  
}

7.总结

一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

三.今天的分享就到这里,如果可以的话可以给小编点一个👍

相关文章:

Java23种设计模式之【单例模式】

目录 一.单例模式的起源,和应用场景 1.单例模式的前世今生! 2.什么是单例模式? 2.1使用单例模式的注意事项 2.2如何理解单例模式? 2.3单例模式的优势以及不足! 2.4使用场景 二.实现 1.实现思路 1.1创建一个 S…...

SQLserver基础入门理论(超基础)二

♥️作者:小刘在C站 ♥️个人主页: 小刘主页 ♥️努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生! ♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏&#xf…...

macbookpro怎么删除软件没有鼠标

macbookpro怎么删除软件没有鼠标,macbookpro触摸板可以替代鼠标进行操作。左右键功能与鼠标相同,可用于执行删除操作。此外,还可以利用键盘上的Delete键来删除选中的文件。 删除软件方法 方法1、打开应用程序,键盘按住control,加点…...

华为数通方向HCIP-DataCom H12-821题库(单选题:241-260)

第241题 ​​LS Request​​报文不包括以下哪一字段? A、通告路由器(Advertising Router) B、链路状态 ID (Link Srate ID) C、数据库描述序列号(Database Dascription Sequence lumber) D、链路状态类型 Link state type) 答案:C 解析: LS Request 报文中包括以下字段…...

PHP8内置函数中的变量函数-PHP8知识详解

在php8中,与变量相关的内置函数比较多,本文说一些比较重要的、常见的内置函数。今日着重讲解了5个,分别是:检测变量是否为空的函数empty()、判断变量是否定义过的函数isset()、销毁指定的变量的函数unset()、获取变量的类型的函数…...

9月3日,每日信息差

第一、中国中铁与广州市城中村改造做地主体签署战略合作框架协议。根据协议,双方将积极响应广州市统筹做地推进高质量发展工作精神,充分发挥双方优势资源,共同加大在物业复建安置、基础设施建设、综合开发投资、城中村改造(微改造…...

2023年了,java后端还有未来吗?

前言 Java当下确实是比较的内卷,但关键在于个人,可以看看不同地方(这里主要举例北上广深一线城市)对于Java开发工程师这个职位的具体要求: 在以下北上广深这些一线大城市的面试招聘当中不难看出,凡是工资…...

使用cmake,将github上的某一个库进行集成到vs2022上

可以参考如下链接的内容: (还未完成,将在后序补充) 1.首先使用cmake,得到对应库的lib,include,bin文件夹 可以参考 https://www.youtube.com/watch?vu5-Df1YlxCI 2.现在我用cmake对这个第三方库进行编译,生成了三个文件夹:一个放的是lib文件(lib文件…...

第二张微服务的调用与注册

文章目录 工程导入利用RestTemplate调用服务需求创建RestTemplate的实例到Spring容器使用RestTemplate发送请求消费者和提供者 Eureka注册中心服务远程调用会出现的问题Eureka的结构和作用Eureka的配置过程搭建注册中心服务注册服务发现 Ribbon负载均衡负载均衡原理源码跟踪总结…...

iWatch框架设计

iWatch框架设计 一、项目框架结构设计 1、项目文件介绍 OverSeaProject:是IOS相关文件文件内容iWatchApp和iWatch Extension:是之前使用xcode14之前的xcode创建的360 app的Watch App,产生的文件结构,包含一个app和Extension的ta…...

【python】读取.dat格式文件

import binascii# 打开二进制文件以只读二进制模式 with open(EXCEL/文件.dat, rb) as file:binary_data file.read()print(binary_data)# 将二进制数据转换为十六进制字符串 hex_data binascii.hexlify(binary_data).decode(utf-8) # binary_data 现在包含了文件的二进制内容…...

机器学习课后习题 --- 朴素贝叶斯

(一)单选题 1.假设会开车的本科生比例是15%,会开车的研究生比例是23%。若在某大学研究生占学生比例是20%,则会开车的学生是研究生的概率是多少? A:80%B:16.6% C:23% D:15% 2.下列关于朴素贝叶斯的特点说法错误的是…...

【设备树笔记整理7】实践操作

1 使用设备树给DM9000网卡_触摸屏指定中断 1.1 修改方法 根据设备节点的compatible属性,在驱动程序中构造/注册 platform_driver,在 platform_driver 的 probe 函数中获得中断资源。 1.2 实验方法 以下是修改好的代码:第6课第1节_网卡_触摸…...

使用VisualStudio制作上位机(六)

文章目录 使用VisualStudio制作上位机(六)第五部分:应用程序打包第一步:勾选为Release模式第二步:生成解决方案第三步:将我们额外添加的文件放入到Release这个文件夹里 使用VisualStudio制作上位机&#xf…...

包管理工具--》npm的配置及使用(一)

目录 🌟概念 🌟背景 🌟前端包管理器 🌟包的安装 本地安装 全局安装 🌟包配置 配置文件 保存依赖关系 🌟包的使用 🌟写在最后 🌟概念 模块(module&#xff09…...

期货基础知识

一、期货是什么?  期货是与现货相对应,并由现货衍生而来。期货通常指期货合约,期货与现货完全不同,现货是实实在在可以交易的货(商品),期货主要不是货,而是以某种大众产品如棉花、大…...

NC后端扩展开发

前言 在日常的工作中,会遇到各种各样的需要进行扩展开发的需求,可以使用系统预留的扩展开发机制来实现,避免修改源码。因NC产品已迭代至BIP版本,所以前端扩展方式就再进行不赘述了,本文主要介绍后端扩展开发方式&…...

nginx vue2+webpack 和 vue3+vite 配置二级目录访问

我们开发中会遇到这样的需求,让我们用服务器nginx部署一个用域名的二级目录来访问项目 https:xxx/二级目录/来放访问项目 目录 思路 1、nginx配置(vue2 和 vue3配置的nginx相同) 2、vue2webpack的配置 (1&#xff0…...

无需租云服务器,Linux本地搭建web服务,并内网穿透发布公网访问

文章目录 前言1. 本地搭建web站点2. 测试局域网访问3. 公开本地web网站3.1 安装cpolar内网穿透3.2 创建http隧道,指向本地80端口3.3 配置后台服务 4. 配置固定二级子域名5. 测试使用固定二级子域名访问本地web站点 前言 在web项目中,部署的web站点需要被外部访问,则…...

算法leetcode|76. 最小覆盖子串(rust重拳出击)

文章目录 76. 最小覆盖子串:样例 1:样例 2:样例 3:提示:进阶: 分析:在这里插入图片描述 题解:rust:go:c:python:java: 76.…...

如何让你的jupyter notebook 排版得像Word(Markdown和网页文件写法)

案例背景 很多时候我们在jupyter notebook里面的写代码,画图,但是文字分析什么的写在里面纯文本不好看,需要进行排版,那么就得用markdown的写法,如何还想居中或者更花里胡哨的字体,那就得要网页文件的一些…...

AndroidTV端:酒店扫码认证投屏DLNA

被老板叼了几次了,最近实在忍不了,准备离职; 但是担心离职后长时间没有办法找到工作 就想贡献一套平时琢磨出来的程序,请各位有能力的话带我熬过这凛冽的寒冬。 目前写出来的,有三个端:安卓TV端&#xf…...

基于PyTorch的交通标志目标检测系统

一、开发环境 Windows 10PyCharm 2021.3.2Python 3.7PyTorch 1.7.0 二、制作交通标志数据集,如下图 三、配置好数据集的地址,然后开始训练 python train.py --data traffic_data.yaml --cfg traffic_yolov5s.yaml --weights pretrained/yolov5s.pt --e…...

feign调用失败 feign.RetryableException: xxx-service executing GET http://xxx/test

一。 问题引入 升级springcloud的版本后 突然发现 以前正常的feign调用也报错了 升级后的各组件版本如下 spring cloud 2021.0.5 spring cloud alibaba 2021.0.5.0 spring boot 2.6.13 错误日志如下 feign.RetryableException: xxx-service executing GET http://xxx-servic…...

mysql 用户管理

目录 用户 创建用户 删除用户 修改密码 权限管理 赋权 查看权限 插销权限 总结 用户 mysql 的用户都存在于系统数据库 mysql 的user 表中 mysql> show tables; --------------------------- | Tables_in_mysql | --------------------------- | column…...

pyinstaller打包exe运行闪退

这里写自定义目录标题 前言问题描述解决过程 前言 闪退原因可能有很多,这里记录下我遇到的问题,简单来说是dll调用错误导致的闪退,因为我的python用的是32位的,但是pyinstaller却是64位的,属于用conda的时候没注意。 …...

ARM 汇编基础知识

1.为什么学习汇编? 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编,因为 Cortex-A 芯片一 上电 SP 指针还没初始化, C 环境还没准备好,所以肯定不能运行 C 代码,必须先用汇编语言设置好 C 环境…...

CRM 自动化如何改善销售和客户服务?

许多 B2B 和 B2C 公司都使用 CRM 系统来组织业务流程,使复杂的任务更容易完成。企业可以使用 CRM 自动化来自动化工作流程,让团队有更多的时间来执行高价值的任务,而不是陷于一堆琐碎事情中。 什么是CRM自动化? CRM 自动化是指 C…...

Bean 的六种作用域

目录 一、作用域是什么? 1、singleton(单例作用域) 2、prototype(原型作用域) 3、request(请求作用域) 4、session(回话作用域) 5、application(全局作用域&a…...

go语言--锁

锁的基础,go的锁是构建在原子操作和信号锁之上的 原子锁 原子包实现协程的对同一个数据的操作,可以实现原子操作,只能用于简单变量的简单操作,可以把多个操作变成一个操作 sema锁 也叫信号量锁/信号锁 核心是一个uint32值&#…...

wordpress个人网站赚钱/seo内容优化心得

本篇下文首发于我的博客 说在前面 有时候我们将项目托管至github之后才发现,我们可能需要删除部分指定的目录或者文件,但是直接在.gitignore文件标注说明,推送到github之后,你会发现想要删除的目录仍然没有删除,所以此时我们需要使用git命令来进行删除. 删除指定目录或文件 先删…...

王烨重生/百度seo优化服务项目

这个题就是让你求出S点到T点的第K短路, 使用A*搜索就可以, 搜索使用两个指标函数 h g, h表示从源点到当前点的最短路, g点表示从当前点到汇点的最短路, 搜索的时候v顶点第k次出队时的h就是第k短路的长度, 代码如下&…...

如何自己建立网站/公司如何在百度宣传

Dubbo自定义Filter统一处理异常参考文章: (1)Dubbo自定义Filter统一处理异常 (2)https://www.cnblogs.com/gossip/p/11734654.html 备忘一下。...

网站建设上海公司/东莞网站营销

最近把自己的工作平台都迁到ubuntu上了,所以要把环境搭起来,首先要安装的是Boost库。 Boost库可以说是STL里非常好用的一个库。1、获得Boost库直接在命令行中输入:apt-get install libboost-dev libboost-dbg libboost-doc bcp libboost-*&am…...

wordpress自定义查询/百度seo关键词优化软件

开发环境 windows7 64、intellij idea 14.1.5、spark-1.5.2、scala 2.0.4、java1.7、maven3.05 将spark中的assembly包引入即可使用local模式运行相关的scala任务,注意不要使用scala2.11,非要使用的话先用这个版本的scala编译一遍spark哈 代码部分 pom文件 先附…...

做网站说要自己贴税点是怎么回事呀/近期新闻热点

推荐地址:推荐这款 软件源码模板资料.rar 001 01.第1章内容介绍.flv 003 03.项目介绍-项目概述.flv 004 04.项目介绍-功能模块和业务流程.flv 005 05.项目技术架构-软件架构的演进-从单体到SOA.flv 006 06.项目技术架构-软件架构的演进-微服务架构.flv 007 07.项目…...