设计模式-单例模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述单例模式的:

作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

 

 单例模式的特点:

  • 单例类只能有一个实例
  • 单例类必须自已创建自已唯一的实例
  • 单例类必须给所有其它对象提供这一实例

饿汉单例类, 饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。

//饿汉式kotlin实现

    object EagerSingleTon

//等于如下java代码

    /**
     * public static final class EagerSingleTon {
        public static final Main.EagerSingleTon INSTANCE;

        private EagerSingleTon() {
        }

        static {
            Main.EagerSingleTon var0 = new Main.EagerSingleTon();
            INSTANCE = var0;
        }
    }
     * */

懒汉单例类,懒汉式其实是一种比较形象的称谓。既然懒,那么在创建对象实例的时候就不着急。会一直等到马上要使用对象实例的时候才会创建,懒人嘛,总是推脱不开的时候才会真正去执行工作,因此在装载对象的时候不创建对象实例。

class LazySingleton private constructor() {
    companion object {
        val instance: LazySingleton by lazy {
            LazySingleton()
        }
    }
}

由于懒汉式的实现是线程安全的,这样会降低整个访问的速度,而且每次都要判断。

双重检查加锁

  可以使用“双重检查加锁”的方式来实现,就可以既实现线程安全,又能够使性能不受很大的影响

class LazySingleton private constructor() {
    companion object {
        //双重锁实现
        val instance: LazySingleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            LazySingleton()
        }
    }
}

所谓“双重检查加锁”机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查,进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

另外,我们运用到了kotlin的延迟属性 Lazy:

 Lazy是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。

原文地址:https://www.cnblogs.com/johnnyzhao/p/10406166.html