单例模式学习
2021/11/26 23:41:15
本文主要是介绍单例模式学习,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
单例模式
概念
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有某个对象被创建;而且还提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
保证一个类只有一个实例:如果你创建了一个对象,同时过一会后决定再创建一个新对象,此时会获得之前已创建的对象,而不是一个新对象。注意:普通构造函数无法实现上述行为,因为构造函数的设计决定了它必须总是返回一个新对象
为该实例提供一个全局访问节点:和全局变量一样,单例模式也允许在程序的任何地方访问特定对象。但是它可以保护该实例不被其他代码覆盖。
优点
- 只生成一个实例,减少了系统的性能开销和内存开支
(目的可能为了控制某些共享资源(如数据库或文件)的访问权限 - 可以避免对资源的多重占用
- 可以在系统设置全局的访问点,优化和共享资源访问
缺点
- 单例模式一般没有接口,扩展困难,若要扩展,除了修改代码基本上没有第二种途径可以实现
- 若单例模式没有实现,是不能进行测试的
- 单例类的职责过重,在一定程度上违背了“单一职责原则”
结构类图
创建方式
- 饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。
- 懒汉式:类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。
- 静态内部方式:结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。
- 枚举单例: 使用枚举实现单例模式。优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。
- 双重检测锁方式 (因为JVM本质重排序的原因,可能会初始化多次,不推荐使用)
如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。
如果需要延迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒汉式。 最好使用饿汉式
实现
所有单例的实现都包含以下两个相同的步骤:
- 将默认构造函数设为私有, 防止其他对象使用单例类的
new
运算符。 - 新建一个静态构建方法作为构造函数。 该函数会 “偷偷” 调用私有构造函数来创建对象, 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。
如果你的代码能够访问单例类, 那它就能调用单例类的静态方法。 无论何时调用该方法, 它总是会返回相同的对象。
一、懒汉式
synchronized
将整个 getInstance() 方法设为同步(synchronized)。不高效,因为任何时候只能有一个线程调用getInstance() 方法,而同步操作只需要在第一次创建单例实例对象时才需要。
public class Singleton{ private static Singleton instance; // 加 synchronized 保证只有一个线程进入方法 public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
双重检验锁模式DCL
同步块加锁
public class Singleton{ // 声明成 static volatile private static volatile Singleton instance; // 私有,使外界构造方法失效 private Singleton(){ } // 声明成 static public static Singleton getInstance(){ // 非空时直接返回 if(instance == null){ synchronized(Singleton.class){ // 防止生成多个实例 if(instance == null){ instance = new Singleton(); } } } return instance; } }
第一个if非空直接返回,减少synchronized浪费性能
第二个if防止生成多个实例
懒汉式 静态内部类
public class Singleton{ // 静态内部类只会被加载一次,故 instance 单例且线程安全 private static class SingletonHolder { private static final Singleton instance = new Singleton(); } // getInstance()方法调用时才加载静态内部类 public static final Singleton getInstance(){ return SingletonHolder.instance; } }
二、饿汉式
- static:第一次加载类到内存中时就会初始化
- final :保持引用变量instance指向值不变
public class Singleton{ // 饿汉式 private static final Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } }
三、枚举
public class Singleton{ /** *枚举类型是线程安全的,并且只会装载一次 */ public enum SingletonEnum{ INSTANCE; private final Singleton instance; SingletonEnum(){ instance = new Singleton(); } private Singleton getInstance(){ return instance; } } public static Singleton getInstance(){ return SingletonEnum.INSTANCE.getInstance(); } }
这篇关于单例模式学习的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)