若是我想定义单例模式,那么它应该是这样的:java
单例是一种软件设计模式,它保证一个类只有一个实例,而且该类提供对该实例的全局访问控制。git
在 Java
中,一般这样写:github
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
复制代码
可是上面的代码在多线程场景下是有缺陷的。若是两个线程同时获取实例,则可能会建立两个实例。因此对于上面的代码咱们须要改造。设计模式
class Singleton {
private static Singleton instance = null;
private Singleton() {
}
private synchronized static void createInstance() {
if (instance == null) {
instance = new Singleton();
}
}
public static Singleton getInstance() {
if (instance == null) createInstance();
return instance;
}
}
复制代码
经过 synchronized
关键字能够确保在建立 instance
时没有线程冲突,只建立一个实例。安全
在 Kotlin
中能够这样实现:多线程
class Singleton private constructor() {
private object HOLDER {
val INSTANCE = Singleton()
}
companion object {
val instance: Singleton by lazy { HOLDER.INSTANCE }
}
}
复制代码
在上面的例子中,能够看到经过 by lazy{}
确保只在第一次获取实例时触发,即 lazy
和 synchronized
关键字的效果同样。ide
固然对于单例模式,Kotlin
提供了 object
的实现方式。函数
object Singleton
复制代码
仅仅一行代码就能够实现单例模式。post
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
复制代码
就像声明变量同样,可是 object
的声明不是表达式,不能进行赋值。object
声明是线程安全的。spa
要使用 object
声明的对象,能够直接调用。
DataProviderManager.registerDataProvider(...)
复制代码
一样,object
声明的类能够具备父类。
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { ... }
override fun mouseEntered(e: MouseEvent) { ... }
}
复制代码
Kotlin
经过 object
关键字实现单例;object
类能够包含属性、函数以及 init
块;object
是线程安全的。