回顾一下单例模式

简介: 回顾一下单例模式

       在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();
}
相关文章
|
21天前
|
C++
C++单例模式
C++中使用模板实现单例模式的方法,并通过一个具体的类A示例展示了如何创建和使用单例。
27 2
|
5月前
|
设计模式 安全 Java
单例模式分享
单例模式分享
20 0
|
设计模式 安全 编译器
2023-6-12-第三式单例模式
2023-6-12-第三式单例模式
72 0
|
6月前
|
C++
【C++ 单例模式】
【C++ 单例模式】
|
设计模式 Java Spring
什么场景要使用单例模式,什么场景不能使用?
经常有小伙伴问我,设计模式学了这么久,每次看到概念也都能理解。但是,就是不知道怎么用,在哪里能用?我告诉大家,设计模式,不是为了要用而用的,而是作为前人总结下来的经验,等到哪天需要用的时候,你能想起来为你所用。
99 0
|
设计模式 缓存 JSON
没那么简单的单例模式
没那么简单的单例模式
125 0
没那么简单的单例模式
|
数据采集 设计模式 算法
大佬,人人都说精通的单例模式,你精通了吗
大佬,人人都说精通的单例模式,你精通了吗
84 0
大佬,人人都说精通的单例模式,你精通了吗
|
设计模式 数据库 Python
|
开发框架 安全 Java
单例模式的应用(1)
单例模式的应用(1)
143 0
|
安全 Java 容器
单例模式的应用(3)
单例模式的应用(3)
169 0