跳至主要內容

单例模式

Neo大约 3 分钟编程Java设计模式

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点以访问该实例。单例模式通常用于控制对资源的访问,如数据库连接、日志记录、线程池等,以确保在整个应用程序中只有一个实例存在。

单例模式

单例模式的特点:

单一实例: 单例模式确保一个类只有一个实例。 全局访问点: 提供一个全局的访问点,使得其他类可以方便地访问该实例。

Java 代码示例:

// 饿汉单例模式
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();   // 在一开始先不进行对象创建
    
    // 将构造方法设置为私有,不允许new对象
    private Singleton() {
    }
    
    public static Singleton getInstance() {   // 获取全局唯一的单例对象
        return INSTANCE;
    }
}


/**
 * @Description
 *      懒汉模式写法1
 *          缺点 线程不安全
 * @Author Ligp
 * @Date 2023/11/28
 */
class Singleton1 {
    private static Singleton1 INSTANCE;   // 在一开始先不进行对象创建
    
    private Singleton1() {
    }   // 不用多说了吧
    
    public static Singleton1 getInstance() {   // 将对象的创建延后到需要时再进行
        if (INSTANCE == null) {    // 如果实例为空,那么就进行创建,不为空说明已经创建过了,那么就直接返回
            INSTANCE = new Singleton1();
        }
        return INSTANCE;
    }
}

/**
 * @Description
 *      懒汉模式写法2
 *          缺点: 方法添加synchronized,执行效率低
 * @Author Ligp
 * @Date 2023/11/28
 */
class Singleton2 {
    private static Singleton2 INSTANCE;   // 在一开始先不进行对象创建
    
    private Singleton2() {
    }
    
    // 方法必须添加synchronized关键字加锁
    public static synchronized Singleton2 getInstance() {   // 将对象的创建延后到需要时再进行
        if (INSTANCE == null) {    // 如果实例为空,那么就进行创建,不为空说明已经创建过了,那么就直接返回
            INSTANCE = new Singleton2();
        }
        return INSTANCE;
    }
}

/**
 * @Description
 *      懒汉模式写法3
 *          缺点: 仍然存在多个线程同时判断为null进入线程等待
 * @Author Ligp
 * @Date 2023/11/28
 */
class Singleton3 {
    private static Singleton3 INSTANCE;   // 在一开始先不进行对象创建
    
    private Singleton3() {
    }
    
    // 方法必须添加synchronized关键字加锁
    public static Singleton3 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton3.class) {
                INSTANCE = new Singleton3();
            }
        }
        return INSTANCE;
    }
}

/**
 * @Description
 *      懒汉模式写法4
 *          缺点: 虽然实现了多线程安全,但是写法过于复杂,代码量多
 * @Author Ligp
 * @Date 2023/11/28
 */
class Singleton4 {
    private static volatile Singleton4 INSTANCE;   // 在一开始先不进行对象创建
    
    private Singleton4() {
    }
    
    // 方法必须添加synchronized关键字加锁
    public static Singleton4 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton4.class) {
                if (INSTANCE == null) INSTANCE = new Singleton4(); // 创建前再判断一下是否有实例
            }
        }
        return INSTANCE;
    }
}


/**
 * @Description
 *      最完美的懒汉式解决方案,没有加锁操作,也能保证
 *
 * @Author Ligp
 * @Date 2023/11/29
 */
class Singleton5 {
    private Singleton5() {
    }
    
    // 由静态内部类持有单例对象,但是根据类加载特性,我们仅使用Singleton类时,不会对静态内部类进行初始化
    private static class Holder {
        private static Singleton5 INSTANCE = new Singleton5();
    }
    
    static Singleton5 getInstance() {// 只有真正使用内部类时,才会进行类初始化
        return Holder.INSTANCE;// 直接获取内部类中的
    }
}

class SingletonTest {
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton1 instance1 = Singleton1.getInstance();
        Singleton2 instance2 = Singleton2.getInstance();
        Singleton3 instance3 = Singleton3.getInstance();
        Singleton4 instance4 = Singleton4.getInstance();
        Singleton5 instance5 = Singleton5.getInstance();
        System.out.println(instance);
        System.out.println(instance1);
        System.out.println(instance2);
        System.out.println(instance3);
        System.out.println(instance4);
        System.out.println(instance5);
    }
}

参考资料:柏码 - 让每一行代码都闪耀智慧的光芒!open in new window、ChatGPT