【Java】设计模式——单例设计模式

1.什么是设计模式

设计模式是一种被广泛认可的、可复用的解决方案,用于在软件开发中解决常见的问题。它们是对软件设计中常见问题的总结与提炼,提供了一套可遵循的标准和最佳实践,帮助开发人员构建高效、可维护和灵活的系统。


2.设计模式的分类

设计模式通常分为三大类:

1.创建型模式:关注如何创建对象,主要解决对象创建过程中的问题。常见的创建型模式包括:

  • 单例模式:确保一个类只有一个实例。
  • 工厂模式:提供创建对象的接口,允许子类决定实例化哪一个类。
  • 抽象工厂模式:提供一个接口,用于创建一系列相关或相互依赖的对象。
  • 结构型模式:关注如何将类或对象组合成更大的结构,主要解决类与对象之间的关系。常见的结构型模式包括:

2.适配器模式:将一个类的接口转换成客户端所期望的另一种接口。

  • 装饰者模式:动态地给对象添加额外的功能。
  • 代理模式:为其他对象提供一种代理,以控制对这个对象的访问。

3.行为型模式:关注对象之间的通信和责任分配,主要解决对象的交互与职责。常见的行为型模式包括:

  • 观察者模式:定义对象间的一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。
  • 策略模式:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。
  • 命令模式:将请求封装成对象,从而使你可以用不同的请求对客户进行参数化。

3.单例设计模式

单例设计模式(Singleton Pattern)是一种常见的设计模式,属于创建型模式。所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例 ,并且该类只提供一个取得其对象实例的方法(静态方法)。这种模式常用于需要控制访问共享资源的场景,例如数据库连接、配置管理等。


3.1 特点

  • 唯一性:类只能有一个实例。
  • 全局访问:提供一个静态方法获取该实例。
  • 延迟加载:实例在首次使用时创建,避免不必要的内存占用。

3.2 实现方式

单例模式可以通过多种方式实现,下面介绍几种常用的方法。

3.2.1 懒汉式(Lazy Initialization)

  • 线程不安全方式(不推荐)
//懒汉式(线程不安全)
class LazySingleTon {// 构造器私有化,外部无法通过new创建对象private LazySingleTon() {}// 本类内部创建对象实例private static LazySingleTon instance;// 提供一个公有的静态方法供外部使用,返回实例对象public static LazySingleTon getInstance() {if(instance == null) {instance = new LazySingleTon();}return instance;}
}

优点: 起到了Lazy Loading的效果,但是只能在单线程下使用。

缺点: 多线程下可能出现多个线程同时获取到instance 为null的情况,这时便会产生多个实例。


  • 线程安全方式(推荐)
class LazySingleTon{// 私有构造器,防止外部通过 new 创建对象private LazySingleTon() {}// 静态内部类,只有在第一次调用 getInstance 方法时才会被加载private static class Holder {private static final LazySingleTon INSTANCE = new LazySingleTon();}// 提供公有的静态方法供外部使用,返回实例对象public static LazySingleTon getInstance() {return Holder.INSTANCE; // 返回静态内部类中的实例}
}

优点: 由于静态内部类的加载是懒加载且由 JVM 保证其线程安全,Java 的类加载机制是由 JVM 负责的,类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入,被阻塞,直到初始化完成。这防止了多个线程同时创建类实例的情况。

缺点: 如果 SingleTon 类加载的时机与应用程序启动时间不一致,可能导致首次访问的延迟。


3.2.2 饿汉式(Eager Initialization)

public class EagerSingleton {// 在类加载时就实例化单例对象,确保在静态上下文中只有一个实例private static final EagerSingleton instance = new EagerSingleton();// 私有构造器,防止外部通过 new 创建对象private EagerSingleton() {}// 提供公有的静态方法供外部获取实例public static EagerSingleton getInstance() {return instance;}
}

优点: 实现简单,无需处理线程安全。

缺点: 在应用启动时就创建实例,如果从始至终从未使用过这个实例,则会造成内存的浪费。


3.2.3 双重检查锁(Double-Check Locking)

public class DoubleCheckSingleton {private volatile static DoubleCheckSingleton instance;// 私有构造函数,防止外部实例化private DoubleCheckSingleton() {}public static DoubleCheckSingleton getInstance() {//先判断对象是否已经实例过,没有实例化过才进入加锁代码if (instance == null) { synchronized (DoubleCheckSingleton.class) {//类对象加锁if (instance == null) { instance = new DoubleCheckSingleton();}}}return instance;}
}

注意: instance 采用 volatile 关键字修饰是很有必要的, instance = new DoubleCheckSingleton()其实是分为三步执行:

1.为 instance分配内存空间
2.初始化 instance
3.将 instance指向分配的内存地址

但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getInstance() 后发现 instance不为空,因此返回 instance,但此时 instance还未被初始化。

优点: 线程安全、延迟加载、效率较高,在实际开发中,推荐使用这种单例设计模式。


3.2.4 枚举单例

public enum EnumSingleton {INSTANCE;// 可以添加其他方法或字段public void someMethod() {// 实现具体的逻辑}
}

优点:

  • 使用 enum 定义的 INSTANCE 是唯一的。Java 的枚举类型在 JVM 中保证了单例,因为每个枚举值在类加载时就被创建,且不会被再创建
  • 枚举类型自动提供序列化机制,避免了传统单例模式中需要处理的序列化问题。即使通过反序列化,返回的也是同一个实例。
  • 枚举实例的创建是线程安全的,不需要显式的同步。

4.总结

单例设计模式适用于当需要控制资源共享(如数据库连接、线程池)、应用程序需要一个全局访问点或需要提供全局状态或配置信息的情况下使用。

单例设计模式通过控制实例化过程,为系统提供了一个灵活的解决方案,确保资源有效利用和访问一致性。不同的实现方式各有优缺点,开发者可以根据具体需求选择合适的实现。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全入门篇之详细学习路线

什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性&…

什么是大数据治理?在企业数字化转型过程中有什么用?

建设背景 有效的数据治理不仅能够确保数据的安全和质量,还能为企业提供深入的业务洞察,推动决策制定和创新。数据治理是数字化转型的基础,是数据资源成为数据资产的基础,只有经过了数据治理,相应的数据资源才能产生价…

Kalshi PK Polymarket,谁更胜一筹

https://kalshi.com https://polymarket.com/ 在刚过去的2024 美大选中,这两个网站可谓风光无限。这两者究竟有何区别呢,今天咱们一起来扒一扒。 Kalshi与Polymarket主要有以下区别: 监管与合法性方面: Kalshi:经过美…

UI测试还在Selenium,难怪你会被淘汰

一、前言 在UI自动化测试的领域中,Selenium无疑是一颗璀璨的明星,它以其强大的浏览器自动化能力,长期以来一直是众多测试工程师的首选工具。它很经典,地位也毋庸置疑,但也是过去式了,现在我采用的自动化方…

基于ssm的网上药房管理系统的设计与实现(源码+LW+调试)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于java的ssm网上药房管…

godot——主题、Theme、StyleBox

我刚开始被这些术语吓到了,一直不敢去接触它们,都用的默认样式。现在好不容易有点思路了,记录下来。 下面看看怎么自定义样式。 1.先新建一个Theme 2.再次点击创建好的Theme 得到 图1 这样一个面板。(看不懂没事,继…

如何利用Python API接口实战中高效地获取商品详情信息

在电商数据分析和商品信息集成领域,高效地获取商品详情信息是至关重要的。本文将介绍如何使用Python结合API接口,从淘宝/天猫平台获取商品详情信息,并提供实战代码示例。 一、理解API接口的重要性 API(应用程序编程接口&#xff…

【Linux】编辑器vim 与 编译器gcc/g++

目录 一、编辑器vim: 1、对vim初步理解: 2、vim的模式: 3、进入与退出: 4、vim命令模式下的指令集: 移动光标: 删除: cv: 撤销: 其他: 5、vim底行模…

不支持UEFI的老显卡修改vBIOS进行支持

前段时间要在办公室玩恐怖黎明,但是联想自带的GT730实在是有点慢,后来闲鱼收了一张HD7750,虽然也是老掉牙,但是性能也有3成提升,聊胜于无吧.但是存在HD7750不支持UEFI的问题.具体表现为: 系统是win11未进系统时,什么都不显示,不能进BIOS.刚换卡未装驱动的时候,即使已经进入系统…

qt QWheelEvent详解

1、概述 QWheelEvent是Qt框架中用于处理鼠标滚轮事件的一个类。当用户滚动鼠标滚轮时,Qt会生成一个QWheelEvent事件,并将其发送到相应的窗口或控件。开发者可以通过重载窗口或控件的wheelEvent()方法来响应这个事件,并执行相应的操作&#x…

如何训练最懂您企业的AI助理?

随着人工智能技术的蓬勃发展,企业级AI助理已成为提升工作效率、优化客户服务体验的重要利器。这些智慧化的系统,通过模拟人类的认知功能,能够轻松应对复杂的数据分析、自动化繁琐的日常任务,甚至为企业决策提供有力支持。拥有一款…

2024网鼎杯web1+re2 wp

这两道题属于比较简单的,顺道说一下,今年的题有点抽象,web不是misc,re不是web的,也有可能时代在进步,现在要求全栈✌了吧 web1 最开始被强网的小浣熊带偏思路了,进来疯狂找sql注入&#xff0c…

【Android 系统中使用CallStack类来追踪获取和操作调用栈信息】

Android系统CallStack类的使用 定义使用方法使用场景注意事项应用举例 定义 在 Android 系统中,CallStack 类是一个用于获取和操作调用栈信息的工具类。这个类通常用于调试和日志记录,以帮助开发者了解函数调用的顺序和位置。以下是您提供的代码片段的解…

Vue 组件通信-自定义事件(七)

一、组件自定事件概念 自己定义的事件,包含事件名,事件回调等,定义好之后去给组件使用。也是一种组件的通信方式,适用于子组件传递给父组件。 二、 组件自定义事件实现子传父 1、在父组件中给子组件绑定一个自定义事件 在子组件标…

解决Qt Creator调试“warning: GDB: Failed to set controlling terminal“

本文档详细介绍了在Qt环境中遇到GDB提示Failed to set controlling terminal错误时的解决方案,步骤包括勾选Run in Terminal选项。适合开发者在调试过程中遇到此类问题时参考。 &"warning: GDB: Failed to set controlling terminal: \345\257\271\350\25…

nginx 部署2个相同的vue

起因: 最近遇到一个问题,在前端用nginx 部署 vue, 发现如果前端有改动,如果不适用热更新,而是直接复制项目过去,会404 因此想到用nginx 负载两套相同vue项目,然后一个个复制vue项目就可以了。…

城镇保障性住房管理:SpringBoot技术探索

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…

ssm075学生信息管理系统+jsp(论文+源码)_kaic

毕 业 设 计(论 文) 学生信息管理系统设计与实现 摘 要 传统办法管理学生信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此&#xff…

Linux学习笔记之运行级别和找回root密码

运行级别 运行级别介绍 0:关机 1:单用户(找回丢失密码) 2:多用户状态没有网络服务(基本不用) 3:多用户状态有网络服务(常用,Xshell就是级别3) 4&…

连接到Oracle数据库

使用SQL * Plus连接Oracle数据库服务器 SQL * Plus 是交互式查询工具,我们在安装 Oracle 数据库服务器或客户端时会自动安装。SQL * Plus 有一个命令行界面,允许您连接到 Oracle 数据库服务器并交互执行语句。 注意:如果有使用过 MySQL 或 P…