单例模式

63 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

单例模式

保证一个类在任何情况下都绝对只有一个实例,并且提供一个全局访问点getInstance ​ 需要隐藏其所有构造方法

实现方式

一、预加载模式,它是在类加载时直接创建并初始化单例对象,所以它并不存在线程安全的问题。它是依靠 ClassLoader 类机制,在程序启动时只加载一次,因此不存在线程安全问题。

public class Singleton {
    // 1.防止外部直接 new 对象破坏单例模式
    private Singleton() {}
    // 2.通过私有变量保存单例对象
    private static Singleton instance = new Singleton();
    // 3.提供公共获取单例对象的方法
    public static Singleton getInstance() {
        return instance;
    }
}

二、延迟加载模式,只有在第一次被使用时,才会被初始化。

public class Singleton {
    // 1.防止外部直接 new 对象破坏单例模式
    private Singleton() {}
    // 2.通过私有变量保存单例对象
    private static volatile Singleton instance = null;
    // 3.提供公共获取单例对象的方法
    public static Singleton getInstance() {
        if (instance == null) { // 第一次效验
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次效验
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

三、静态内部类既能保证线程安全,又能保证懒加载,它只有在被调用时,才会通过 ClassLoader 机制来加载和初始化内部静态类,因此它是线程安全的。

public class Singleton {
    // 1.防止外部直接 new 对象破坏单例模式
    private Singleton() {
    }

    // 2.静态内部类
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    // 3.提供公共获取单例对象的方法
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

四、枚举也是在第一次被使用时,才会被 Java 虚拟机加载并初始化,所以它也是线程安全的,且是懒加载的。

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}

单例模式适用于经常被访问的对象,或是创建和销毁需要调用大量资源和时间的对象,使用单例模式可以避免频繁创建和销毁对象。单例模式的常用实现方法有 4 种:预加载模式、延迟加载模式、静态内部类和枚举。从写法的简洁性、线程安全性和代码的易懂性等方面综合来看,博主比较推荐使用枚举或延迟加载模式来实现单例模式。