前言
大家好,我是大聪明。设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
今天我分享一下单例模式的相关知识点,希望对你有所帮助。
单例模式的定义
单例模式是一种常用的创建型设计模式,在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,使用单例模式的类只存在一个对象实例。
单例模式的特点
- 单例类只能有一个实例。
- 单例类必须自己自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例
饿汉式
饿汉式的特点是对象实例在初始化的时候就已经创建好了,不管你有没有使用到,具体代码如下:
public class HungrySingleton {
// 持有自己类的引用
private static final HungrySingleton singleton = new HungrySingleton();
// 私有化构造器
private HungrySingleton(){}
// 提供获取实例的静态方法
public static HungrySingleton getInstance(){
return singleton;
}
}
优点:没有线程安全问题
缺点:初始化阶段创建对象,假设实例化对象十分耗时,并且这个实例最后也没有被使用到,岂不是白白浪费资源
懒汉式
懒汉式的特点是在对象被使用的时候才去实例化,比较懒,在用到的时候会检查有没有实例,如果有直接返回,如若没有则新建再返回,具体代码如下:
public class LazySingleton {
private static LazySingleton singleton;
// 私有化构造器
private LazySingleton(){}
// 提供获取实例的静态方法
public static LazySingleton getInstance(){
// 若对象没有被实例化,则new一下再返回
if (singleton == null) {
singleton = new LazySingleton();
}
return singleton;
}
}
优点:只有当对象被使用的时候才会进行实例化
缺点:这种实现最大的问题就是线程不安全,由于没有加锁,在并发情况下可能会实例化出多个对象
双重检测锁
双重检测锁顾名思义就是采用双重判断锁机制,安全且在多线程的情况下能保持高性能,相当于懒汉式的一个升级版,具体代码如下:
public class DoubleCheckLockingSingleton {
// 注意这里多了一个volatile关键字,面试的时候经常会问这个关键字的作用
private volatile static DoubleCheckLockingSingleton singleton;
// 私有化构造器
private DoubleCheckLockingSingleton(){}
// 提供获取实例的静态方法
public static DoubleCheckLockingSingleton getInstance(){
if (singleton == null) {
synchronized (DoubleCheckLockingSingleton.class) {
if (singleton == null) {
singleton = new DoubleCheckLockingSingleton();
}
}
}
return singleton;
}
}
优点:适合高并发的情况下使用,保证线程安全
缺点:可以通过反射来破坏单例
静态内部类
静态内部类顾名思义就是通过静态的内部类来实现单例模式,这种方式能达到双重检测锁一样的功效,具体代码如下:
public class StaticInnerClassSingleton {
// 静态内部类
private static class SingletonHolder {
private static final StaticInnerClassSingleton singleton = new StaticInnerClassSingleton();
}
// 私有化构造器
private StaticInnerClassSingleton(){}
// 提供获取实例的静态方法
public static StaticInnerClassSingleton getInstance() {
return SingletonHolder.singleton;
}
}
优点:线程安全,利用静态内部类的特点实现延迟加载,效率高
缺点:可以通过反射来破坏单例
枚举
在Java中,枚举就是天然的单例,每一个实例只有一个对象,这是Java底层内部机制提供的保证。
public enum EnumSingleton {
INSTANCE;
}
优点:JVM保证了枚举是天然的单例,线程安全,自动支持序列化机制,防止反序列化重新创建新的对象,防止多次实例化
总结
单例模式的实现有多种方式,分别从是否线程安全、是否懒加载、是否防止反射构建三个方面进行对比,具体如下:
单例模式实现 | 是否线程安全 | 是否懒加载 | 是否防止反射构建 |
---|---|---|---|
饿汉式 | 是 | 否 | 否 |
懒汉式 | 否 | 是 | 否 |
双重检测锁 | 是 | 是 | 否 |
静态内部类 | 是 | 是 | 否 |
枚举 | 是 | 否 | 是 |
单例模式在面试和工作的过程中经常遇到,你在工作中经常用到哪些设计模式呢?欢迎在下方留言。
喜欢本文的朋友们,那你一定喜欢本文吧!那就点个赞吧!