设计模式——单例模式

单例模式定义:保证创建唯一实例。

实现有很多方式但是有一个共同点:构造方法私有化。

单例模式实现需要考虑的问题:

  • 保证单例
  • 延迟加载
  • 线程安全
  • 反反射、反序列化、反克隆

下面各种实现方式就是上述问题的渐进解决。懒汉式+双重验证锁是最常用的。

一、饿汉式

public class SingletonV0 {
    //利用一个类只会被类加载一次创建唯一实例
    private static final SingletonV0 INSTANCE = new SingletonV0();

    private SingletonV0(){}

    public static SingletonV0 getSingletonVo(){
        return INSTANCE;
    }
}

二、懒汉式

public class SingletonV1 {

    private static SingletonV1 INSTANCE;

    private SingletonV1(){}

    public static SingletonV1 getInstance(){
        if (INSTANCE == null){
            //延迟加载
            INSTANCE = new SingletonV1();
        }
        return INSTANCE;
    }
}

三、懒汉式+双重验证锁——最常用的方式

public class SingletonV2 {
    /**
     * 注意细节:volatile修饰
     */
    private static volatile SingletonV2 INSTANCE;

    private SingletonV2(){}

    public static SingletonV2 getInstance(){
        //双重验证锁
        if (INSTANCE == null){
            synchronized (SingletonV2.class){
                if (INSTANCE == null){
                    INSTANCE = new SingletonV2();
                }
            }
        }
        return INSTANCE;
    }
}

四、懒汉式+双重验证锁+反反射+反序列化+反克隆

public class SingletonV3 implements Cloneable, Serializable {
    /**
     * 注意细节:volatile修饰
     */
    private static volatile SingletonV3 INSTANCE;

    private static boolean IS_FIRST_CREATE = true;
    private SingletonV3(){
        //反反射
        if (IS_FIRST_CREATE){
            synchronized (SingletonV3.class){
                if (IS_FIRST_CREATE){
                    IS_FIRST_CREATE = false;
                }
            }
        }else{
            throw new UnsupportedOperationException("singleton object is already init().");
        }
    }

    public static SingletonV3 getInstance(){
        //双重验证锁
        if (INSTANCE == null){
            synchronized (SingletonV3.class){
                if (INSTANCE == null){
                    INSTANCE = new SingletonV3();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 反克隆
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("singleton object not support clone");
    }
    /**
     * 反序列化
     */
    private void readObject(ObjectInputStream in) throws InvalidObjectException {
        throw new InvalidObjectException("can't deserialize singleton");
    }

    private void readObjectNoData() throws InvalidObjectException {
        throw new InvalidObjectException("can't deserialize singleton");
    }
}

五、内部静态类

public class SingletonV4 {

    private SingletonV4(){}

    /**
     * 利用静态内部类的延迟加载
     */
    private static class SingletonHolder{
        private static final SingletonV4 INSTANCE = new SingletonV4();
    }

    public SingletonV4 getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

六、枚举类

用枚举类创建单例是《effective Java》中推荐使用的方法。

枚举类的实质是编译器的一个语法糖,反编译后的代码:java枚举类语法糖

public enum SingletonV5 {

    /**
     * Java的枚举类型其实是一个编译期的一个语法糖
     *  enum 编译后public final class
     *  INSTANCE  编译后 public static final SingletonV5 INSTANCE;
     *  静态块初始化+反克隆+反序列化
     */
    INSTANCE;

}

七、框架中的单例模式

1、Spring单例Bean

Spring中单例模式非常多,基本都是使用懒汉式+双重验证锁的方式创建单例的

最有代表性的实现:Spring单例Bean。

/* org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) */
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

 

posted on 2020-04-03 15:31  FFStayF  阅读(148)  评论(0编辑  收藏  举报