Kotlin-单例实现方式

115 阅读2分钟
object关键字描述

以下定义了单例A,原理大家可以看看注释,其实也挺简单的。

    object A {
        fun test(){}
    }
    
 //反编译代码
public final class A {
   @NotNull
   public static final A INSTANCE;

   public final void test() {
   }

   private A() {
   }

   static {//类加载的时候实例化对象
      A var0 = new A();
      INSTANCE = var0;
   }
}

//调用处
A.test()
//调用处反编译,通过INSTANCE对象来访问
A.INSTANCE.test();
  • 使用场景:对内存影响不大,外部不需要传入参数。
by lazy单例

利用Kotlin by lazy的特性,保证对象只初始化一次,懒加载而且是线程安全。想知道原理可以看下juejin.cn/post/708784…

class MyApplication : Application() {
    val b by lazy { B() }
}

使用场景:对内存较敏感。

双重判断
class B private constructor(context: Context) {

    companion object {
       @Volatile private var instance: B? = null

        @JvmStatic
        fun getInstance(context: Context): B {
            instance ?: synchronized(B::class.java) {//1
                instance ?: {//2
                    instance = B(context)
                }
            }
            return instance!!
        }
    }
}
  • 注释1、2:如果instance为空则执行冒号后面的逻辑;
  • 注释3,将instance返回,不过这里用双引用总感觉有点问题,不知道有没有更好的处理方式。写法跟Java大体类似。 使用场景:对内存较敏感,外部可以传入参数。
单例构建模板

如果多个类要定义成单例,那么以上代码就得写多次,我们可以抽象模板代码。

abstract class BaseSingleInstance<in P, out R> {//1
    @Volatile
    private var instatnce: R? = null//2

    abstract fun create(params: P): R//3

    fun getInstance(params: P): R {//4
        instatnce ?: synchronized(BaseSingleInstance::class.java) {
            instatnce ?: create(params).apply { instatnce = this }
        }
        return instatnce!!
    }
}

//子类实现
class B private constructor(context: Context) {//5

    companion object : BaseSingleInstance<Context, B>() {
        override fun create(params: Context) = B(params)
    }
}
  • 注释1:定义抽象类BaseSingleInstance,给子类伴生类实现,in P 表示入参为P, out R表示返回类型为R,in out控制泛型的作用域,前者为入参使用,后者为返回使用;
  • 注释2:定义instatnce,存储实例对象;
  • 注释3:抽象函数,由子类负责对象的构建;
  • 注释4:获取实例的方法,这个没什么好说的;
  • 注释5:子类B的实现。 使用场景:多个类需要实现单例。

以上分析有不对的地方,请指出,互相学习,谢谢哦!