必知必会:单例设计模式的几种设计方案

151 阅读3分钟

什么是单例设计模式

单例模式,是一种常用的软件设计模式。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

设计的思路是

  1. 别人不能new实例,所以要将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。

  2. 在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型。

  3. 定义一个静态方法返回这个唯一对象。

饿汉式

立即加载就是使用类的时候已经将对象创建完毕,不管以后会不会使用到该实例化对象,先创建了再说。常见的实现办法就是直接new实例化。

public class Singleton {

    // 将自身实例化对象设置为一个属性,并用static、final修饰
    private static final Singleton instance = new Singleton();
    
    // 构造方法私有化
    private Singleton() {}
    
    // 静态方法返回该实例
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

延迟加载就是调用get()方法时实例才被创建,先不急着实例化出对象,等要用的时候才给你创建出来。常见的实现方法就是在get方法中进行new实例化。

public class Singleton {

    // 将自身实例化对象设置为一个属性,并用static修饰
    private static Singleton instance;
    
    // 构造方法私有化
    private Singleton() {}
    
    // 静态方法返回该实例
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这种懒汉式在多线程环境中并不能保证单例的状态,我们必须使用锁机制保证单例状态。具体我们继续往下看

懒汉式+锁机制 简称粗双重检查锁

双重检查锁是线程安全的一种方式,它保证了延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

public class Singleton {  
    // volatile如果不加可能会出现半初始化的对象
    private volatile static Singleton singleton;  
    private Singleton (){}  
    
    public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
                if (singleton == null) {  
                    singleton = new Singleton();  
                }  
            }  
        }  
        return singleton;  
        }  
}

有几个注意的地方:

  • singleton == null 有两层判断,表示的是:

    1. 第一层判断保证的是外部的请求进来不会上锁,如果实例已经创建完毕,会直接返回。
    2. 第二层判断保证的是为了防止生成多个实例
  • 加上volatile是防止指令重排,形成半初始化的对象。

内部类实现单例

这种也是懒汉式的一种实现,而且使用这种懒汉式没有任何的线程问题,在Singleton加载的时候,不会加载SingletonHolder,但是调用getInstance方法的时候,因为主动使用了SingletonHolder这个内部类,就会加载这个内部类,一旦加载这个内部类,静态内部类里面的成员变量才会被初始化,最终实现了懒加载。

public class Singleton {

    /** 私有化构造器 */
    private Singleton() {
    }

    /** 对外提供公共的访问方法 */
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /** 写一个静态内部类,里面实例化外部类 */
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

}

枚举实现单例

package com.ydlclass;

public class Singleton {

    private Singleton(){}

    public static Singleton getInstant(){
        return SingletonHolder.INSTANT.instant;
    }

   private enum SingletonHolder{
        INSTANT;
        private final Singleton instant;

        SingletonHolder(){
            instant = new Singleton();
        }

    }

    public static void main(String[] args) {
        System.out.println(Singleton.getInstant() == Singleton.getInstant());
    }

}