单例模式-Singleton

名称:

      单例模式(Singleton Pattern)-对象创建型模式。

 

问题:

    保证一个类仅有一个实例,并提供一个访问它的全局访问点

    Ensure a class has only one instance, and provide a global point of access to it.

 

适用性:

    -当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

    -当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

 

协作:

    客户只能通过Singleton的Instance操作访问一个Singleton的实例。

 

优点和缺点:

    1、对唯一实例的受控访问。

    2、缩小名空间。

    3、允许对操作和表示的精化。

    4、允许可变数目的实例。

    5、比类操作更灵活。

 

解决方案

    一、饿汉模式

public class HungerSingleton {

    private static HungerSingleton instance = new HungerSingleton();

    private HungerSingleton() {

    }
public static HungerSingleton getInstance() { return instance; } }

 

    说明:1.构造函数私有化,可以阻止用户直接new 一个对象。

             2. static的成员instance在类的加载时创建并实例化,由jvm来保证唯一性。

 

    二、懒汉模式

public class LazySingleton {
    private volatile static LazySingleton instance;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

        说明:volatile关键字   

          1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

      2)禁止进行指令重排序。

 

三、静态内部类

public class InternalClassSingleton {
private static class lazyHolder { private static final InternalClassSingleton instance = new InternalClassSingleton(); }
private InternalClassSingleton() { }
public static InternalClassSingleton getInstance() { return lazyHolder.instance; } }

 

  说明:和饿汉模式对比,静态内部类使用getInstance时才加载。

四、枚举

public class EnumSingleton {
    private EnumSingleton(){

    }
    
    enum Singleton{
        INSTANCE;
        private EnumSingleton enumSingleton;
        private Singleton(){
            enumSingleton = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return enumSingleton;
        }

    }
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }

}

说明:枚举可以防止反射或反序列化来实例化类,而其余方法不可以。

 

 

总结:

      单例模式可以保证类只实例化一个对象。

      但是单例模式又是反模式的。因为单例模式无法继承,无法利用多态特效。而且mock起来也不方便,给单元测试造成困难。

      

参考资料 

Java并发编程:volatile关键字解析

 

posted @ 2020-06-18 14:51  diameter  阅读(53)  评论(0编辑  收藏  举报