写在文前
单例模式应该是开发中用的最多的设计模式了,今天我们就来用Kotlin写一遍单例模式,并与Java单例模式对比,主要是下面几种:
- 懒汉式
- Double Check
- 静态内部类
懒汉式
我们先看Java怎么写的
1 | public class SingletonDemo { |
很简单,再看Kotlin:
1 | object SingletonDemo |
我靠,原谅我要爆粗口,这也太简单了吧,到底有没有实现单例呢?我们查看kotlin Bytecode,然后再Decompile:
1 | public final class singletonDemo { |
我们发现和java代码几乎一样,其实学过Kotlin的同学都知道,这种写法是Kotlin中的对象声明
对象声明将类声明和类实例结合在一起了,对象声明的初始化过程是线程安全的。在Kotlin中没有静态方法,你可以通过对象声明来实现。
Double Check
先看Java:
1 | public class SingletonDemo { |
再看Kotlin,很简单:
1 | class SingletonDemo private constructor() { |
- 显示声明构造函数为private
- companion object 在类中声明一个对象
- 通过延迟属性lazy实现懒加载
- 默认情况下,对于 lazy 属性的求值是同步锁的(synchronized)所以这里是线程安全的
这里有个知识点:延迟属性lazy
lazy() 是接受一个 lambda 并返回一个 Lazy
实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。 默认情况下,对于 lazy 属性的求值是同步锁的(synchronized):该值只在一个线程中计算,并且所有线程会看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。 而如果你确定初始化将总是发生在单个线程,那么你可以使用 LazyThreadSafetyMode.NONE 模式, 它不会有任何线程安全的保证以及相关的开销。
静态内部类
先看Java
1 | public class SingletonDemo { |
再看Kotlin
1 | class SingletonDemo private constructor() { |
可以看到Kotlin的实现和Java基本一致!
写在最后
通过前面三种单例模式的对比,我们发现明显Kotlin代码量会少一点,Kotlin是越用越好用啊,还没有转kotlin的同学抓紧啦。