饿汉式
Java版:
public class SingletonDemo {
private static SingletonDemo instance=new SingletonDemo();
private SingletonDemo(){
}
public static SingletonDemo getInstance(){
return instance;
}
}
Kotlin版:
Kotlin中类没有静态方法,如果需要一个无需类实例,但是需要访问类内部函数的类,可以将这个类声明位为object,代码如下:
object SingletonDemo
懒汉式
线程安全的懒汉式
public class SafeSingletonDemo {
private static SafeSingletonDemo instance;
private SafeSingletonDemo() { }
//使用同步锁解决线程安全问题
public static synchronized SafeSingletonDemo getInstance() {
if (instance == null) {
instance = new SafeSingletonDemo();
}
return instance;
}
}
Kotlin版:
在Kotlin中,使用同步锁需要添加 @Synchronized
class SafeSingletonKtDemo {
companion object {
private var instance: SafeSingletonKtDemo? = null
get() {
if (field == null) {
field = SafeSingletonKtDemo()
}
return field
}
@Synchronized
fun get(): SafeSingletonKtDemo {
return instance!!
}
}
}
双重检查模式
- 构造方法私有化,防止外部调用。
- synchronized同步锁,防止多线程同时创建问题。
- 使用double check,第一个非空判断解决使用同步锁带来的效率问题,仅当未创建实例时进去synchronized代码段,第二个非空判断解决创建多个实例的问题。
- 因为instance = new Single()为非原子操作,而Java使用了指令重排,故多线程时可能出现实例已经创建但未初始化的情况。使用volatile关键字禁用指令重排,可解决问题。
Java版代码:
public class LazySingletonDemo {
//validate关键字禁用指令重排,保证了对象的可见性
private static volatile LazySingletonDemo INSTANCE;
//将构造器私有化防止直接new生成对象
private LazySingletonDemo() { }
public static LazySingletonDemo getInstance() {
//双重检查机制,第一次判空,解决同步锁效率问题,已经创建过则直接返回实例
if (INSTANCE == null) {
synchronized (LazySingletonDemo.class) {
//第二次非空判断,解决创建多个实例的问题
if (INSTANCE == null) {
INSTANCE = new LazySingletonDemo();
}
}
}
return INSTANCE;
}
}
Kotlin版:
Kotlin中借助懒加载属性实现,lazy是一种延迟属性,它接受一个lambda表达式并返回lazy实例,在第一次get()的时候执行lazy中的lambda表达式,同时记录下结果,在后续调用get()时直接返回结果
class LazySingletonKtDemo private constructor() {
companion object {
//lazy延迟属性,接受一个lambda表达式并返回lazy实例
val instance: LazySingletonKtDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
LazySingletonKtDemo()
}
}
}
静态内部类模式
- 使用静态内部类,利用类加载器保证同步性,在内部类中完成实例的创建。因为是内部类,故仅在在外部类相应方法被调用时内部类才会被装载。
- 内部类为饿汉式,外部类为懒汉式,将两者优势结合,十分巧妙。
Java版:
public class SingletonDemo {
private SingletonDemo() { }
private static class SingletonHelper {
private static SingletonDemo instance = new SingletonDemo();
}
public static SingletonDemo getInstance() {
return SingletonHelper.instance;
}
}
Kotlin版:
class SingletonDemo private constructor() {
companion object {
fun get(): SingletonDemo {
return Helper.instance
}
}
private object Helper {
val instance = SingletonDemo()
}
}
总结
可以看到使用Kotlin使得代码更加简洁,对于简单的单例模式更是一行代码解决问题。加之今年Kotlin正式成为安卓首选语言,学习Kotlin已经是大势所趋了。