回顾一下单例模式

简介: 回顾一下单例模式

   在Java的23中设计模式中,单例模式是最简单也是最常考的一个设计模式,实现单例模式的方式有很多种,而且有的实现方式会考虑线程安全和反射机制的破坏,其中最常见的不外乎懒汉模式饿汉模式双重检查式枚举式,加下来就每个方式的单例模式进行代码的实现,以此来做一个对比。

1 懒汉模式

      顾名思义,懒汉就是在需要的时候去做事情,因此懒汉模式就是在需要的时候再去new,进行对象的实例化,等再次需要时先进行检查,如果对象不为空就直接返回。

/**
 * 懒汉式
 *
 * @author 17122
 */
public class LanHanSingleton {
    /**
     * 先声明,不需要new
     */
    private static LanHanSingleton instance;
    /**
     * 构造方法私有,不允许new
     */
    private LanHanSingleton() {
    }
    /**
     * 多线程环境下加入synchronized可保障线程安全
     *
     * @return
     */
    public static synchronized LanHanSingleton getInstance() {
        //检查如果对象为空则重新创建
        if (instance == null) {
            instance = new LanHanSingleton();
        }
        return instance;
    }
}
复制代码


2 饿汉模式

      可以把饿汉当做JVM的类加载器,而需要实例化的对象就是食物,当在JVM类加载时就迫切的进行类的实例化,因此饿汉模式名由此而生。简单的描述就是在类加载时将对象实例化,获取时直接返回。

/**
 * 饿汉式单例
 *
 * @author 17122
 */
public class EHanSingleton {
    /**
     * 初始化类时先创建实例
     */
    private static EHanSingleton instance = new EHanSingleton();
    /**
     * 构造方法私有,不允许new
     */
    private EHanSingleton() {
    }
    public static EHanSingleton getInstance() {
        //返回实例
        return instance;
    }
}
复制代码


3 双重检查式

      双重检查式的实现主要是为了多线程下的安全状态,放在多个线程在第一次if判断时产生相同的结果。而且在第一次if之后加入了对象锁,确保多线程下线程的安全。

/**
 * 双重检查式
 *
 * @author 17122
 */
public class DoubleCheckSingleton {
    /**
     * volatile保证多线程下数据的可见性
     */
    private volatile static DoubleCheckSingleton singleton;
    /**
     * 构造方法私有,不允许new
     */
    private DoubleCheckSingleton() {
    }
    public static DoubleCheckSingleton getSingleton() {
        //第一次检查
        if (singleton == null) {
            //加入对象锁
            synchronized (DoubleCheckSingleton.class) {
                //第二次检查
                if (singleton == null) {
                    singleton = new DoubleCheckSingleton();
                }
            }
        }
        return singleton;
    }
}
复制代码


4 枚举式

      这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

/**
 * 枚举式
 *
 * @author 17122
 */
public enum EnumSingleton {
    INSTANCE;
    /**
     * 返回实例
     *
     * @return
     */
    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
    //以下可以时任意方法
}
复制代码


5 对比

是否线程安全 是否能被反射破坏 多线程下使用效率
懒汉模式 较低
饿汉模式 较高
双重检查式 较高
枚举式 较高

6 扩展:反射如何破坏单例?

/**
 *  反射破坏单例模式
 */
try {
    DoubleCheckSingleton singleton = DoubleCheckSingleton.getSingleton();
    Constructor<DoubleCheckSingleton> constructor = DoubleCheckSingleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    DoubleCheckSingleton instance = constructor.newInstance();
    System.out.println("反射破坏单例:");
    System.out.println(singleton == instance);
} catch (Exception e) {
    e.printStackTrace();
}



相关文章
|
6月前
|
设计模式 安全
详细讲解什么是单例模式
详细讲解什么是单例模式
|
7天前
|
设计模式 安全 C#
C# 单例模式的多种实现
C# 单例模式的多种实现
|
1月前
|
C++
C++单例模式
C++中使用模板实现单例模式的方法,并通过一个具体的类A示例展示了如何创建和使用单例。
29 2
|
5月前
|
设计模式 安全 Java
单例模式分享
单例模式分享
23 0
|
设计模式 安全 编译器
2023-6-12-第三式单例模式
2023-6-12-第三式单例模式
72 0
|
6月前
|
C++
【C++ 单例模式】
【C++ 单例模式】
|
6月前
|
设计模式 安全
【单例模式】—— 每天一点小知识
【单例模式】—— 每天一点小知识
找对象需要单例模式吗?
单例模式的类只提供私有的构造函数
|
SQL 安全 Java
五种单例模式介绍
五种单例模式介绍
91 0
|
设计模式 缓存 JSON
没那么简单的单例模式
没那么简单的单例模式
126 0
没那么简单的单例模式