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

重生之我在Java世界------学单例设计模式

什么是单例设计模式?

单例模式是面向对象编程中最简单却又最常用的设计模式之一。它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的原理、常见实现方法、优缺点,以及在使用过程中可能遇到的陷阱。

单例模式的核心原理

单例模式的实现主要依赖于以下三个要素:

  1. 私有构造函数:防止外部直接创建实例。
  2. 私有静态实例:类的唯一实例。
  3. 公共静态访问方法:提供全局访问点。

这种设计确保了在整个应用程序中,特定的类只会有一个实例存在。单例模式常用于管理共享资源、全局配置或需要统一协调行为的场景。

常见实现方法

懒汉式(线程不安全)

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

这种方法实现了延迟加载,即在第一次调用 getInstance() 方法时才创建实例。然而,它在多线程环境下是不安全的。如果多个线程同时调用 getInstance() 方法,可能会创建多个实例。

饿汉式

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

饿汉式在类加载时就创建了实例,因此天然线程安全。但它没有实现延迟加载,可能会造成资源浪费。

双重检查锁

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

双重检查锁结合了延迟加载和线程安全的优点。它在多线程环境下能够良好工作,同时避免了不必要的同步开销。

静态内部类

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

静态内部类方法既实现了**延迟加载,又保证了线程安全。**它利用了Java的类加载机制来保证只创建一个实例。当 Singleton 类被加载时,SingletonHolder 类并不会被立即初始化,只有当调用 getInstance() 方法时,SingletonHolder 才会被加载,从而创建 INSTANCE。这种方法也被称为 Initialization on Demand Holder (IODH) 模式。

枚举

public enum Singleton {INSTANCE;public void doSomething() {// 方法实现}
}

枚举实现是最简洁的单例模式实现方式。它不仅能避免多线程同步问题,还能防止反序列化重新创建新的对象。。

单例模式的优缺点

**单例模式的主要优点在于它能够确保一个类只有一个实例,提供了对该实例的全局访问点,**并且可以显著节省系统资源。然而,它也存在一些缺点。单例类可能会违反单一职责原则,因为它不仅要管理自己的功能,还要确保自己是唯一实例。此外,单例模式在某些情况下可能会使单元测试变得困难,因为很难模拟单例类的不同状态。

单例模式的潜在陷阱(拓展)

反射机制破坏单例

Java的反射机制可以用来破坏单例。通过反射,可以强制调用私有构造函数,从而创建多个实例。例如:

Singleton instance1 = Singleton.getInstance();
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton instance2 = constructor.newInstance();

为了防止这种情况,可以在构造函数中添加检查,如果实例已经存在,则抛出异常。枚举实现的单例可以有效防止反射攻击。

序列化破坏单例

如果单例类是可序列化的,那么在反序列化时会创建新的实例。为了防止这种情况,可以实现 readResolve() 方法:

private Object readResolve() {return getInstance();
}

同样,枚举实现的单例也天然地防止了序列化问题。

多个类加载器

在使用多个类加载器的环境中,可能会出现多个单例实例。这种情况比较少见,但在复杂的应用服务器环境中可能会遇到。解决方法包括使用上下文类加载器或将单例类放在共享的类路径中。

结语

单例模式虽然概念简单,但在实际应用中需要考虑诸多因素,如线程安全、延迟加载、序列化等。选择合适的实现方法并注意潜在的陷阱,对于正确使用单例模式至关重要。在使用单例模式时,应该根据具体的应用场景和需求,权衡其利弊,做出最适合的选择。

从上述几种实现方法来看,静态内部类和枚举实现都提供了很好的平衡:它们既保证了线程安全,又兼顾了延迟加载(静态内部类)或简洁性(枚举)。特别是枚举实现,它还额外提供了防止反射攻击和序列化问题的保护。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 智谱清影 -CogVideoX-2b-部署与使用,带你揭秘生成6s视频的极致体验!
  • 正点原子阿尔法ARM开发板-IMX6ULL(七)——BSP工程管理实验(补:链接文件和.s文件)
  • 阅信云CTO向永清:35岁不应该成为技术职业发展的瓶颈|OceanBase 《DB大咖说》
  • 比backtrader还简单的量化回测框架,bt的使用方式以及示例
  • SpringCache
  • 简明linux系统编程--共享内存消息队列信号量
  • Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用增强扩展(text2sql)
  • 8.sklearn-模型保存
  • VirtualBox7.1.0 安装 Ubuntu22.04.5 虚拟机
  • @JsonFormat 和 @DateTimeFormat 的区别
  • JavaScript substring() 方法
  • Redisson 分布式锁的使用详解
  • 将有序数组——>二叉搜索树
  • Leetcode 3290. Maximum Multiplication Score
  • Python 数学建模——高斯核密度估计
  • [case10]使用RSQL实现端到端的动态查询
  • ➹使用webpack配置多页面应用(MPA)
  • CSS居中完全指南——构建CSS居中决策树
  • Git同步原始仓库到Fork仓库中
  • Hexo+码云+git快速搭建免费的静态Blog
  • JavaScript设计模式系列一:工厂模式
  • laravel 用artisan创建自己的模板
  • node.js
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • SegmentFault 2015 Top Rank
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 服务器之间,相同帐号,实现免密钥登录
  • 检测对象或数组
  • 聊聊directory traversal attack
  • 前端技术周刊 2019-01-14:客户端存储
  • 试着探索高并发下的系统架构面貌
  • 微信小程序实战练习(仿五洲到家微信版)
  • 我有几个粽子,和一个故事
  • 我这样减少了26.5M Java内存!
  • 携程小程序初体验
  • 找一份好的前端工作,起点很重要
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 我们雇佣了一只大猴子...
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #QT(一种朴素的计算器实现方法)
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (笔试题)分解质因式
  • (二)换源+apt-get基础配置+搜狗拼音
  • (分类)KNN算法- 参数调优
  • (论文阅读30/100)Convolutional Pose Machines
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (一)VirtualBox安装增强功能
  • **PHP分步表单提交思路(分页表单提交)
  • .Net IOC框架入门之一 Unity
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .net 中viewstate的原理和使用
  • .NET连接MongoDB数据库实例教程