为了账号安全,请及时绑定邮箱和手机立即绑定

Kotlin单例模式多种写法大分析

标签:
Kotlin

前言:

今天,在项目开发中,又运用到了单例模式另外一种Kotlin写法,于是决定记录下来,以供参考。

几种单例模式:
  • 饿汉式

  • 双重校验懒汉式

  • 静态内部类式

1. 饿汉式

/**
 * 作者:huangchen on 2018/8/7 21:48
 * 邮箱:huangcftt@gmail.com
 *///java实现public class PayManager {
    private static PayManager payManager = new PayManager();    public static PayManager getPayManager() {        return payManager;
    }    private PayManager(){

    }
}
/**
 * 作者:huangchen on 2018/8/7 21:55
 * 邮箱:huangcftt@gmail.com
 *///Kotlin实现object PayServiceManager

是不是大吃一惊。我靠一个object 关键字就完成相同的功能?一行代码?

Kotlin的对象声明学习了Kotlin的小伙伴肯定知道,在Kotlin中类没有静态方法。如果你需要写一个可以无需用一个类的实例来调用,但需要访问类内部的函数(例如,工厂方法,单例等),你可以把该类声明为一个对象。该对象与其他语言的静态成员是类似的。

对象声明的初始化过程是线程安全的。

查看kotlin Bytecode 后 Decompile后:

@Metadata(
   mv = {1, 1, 9},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\bÆ\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
   d2 = {"Lcn/yonghui/shop/shopapplication/pay/config/PayServiceManager;", "", "()V", "production sources for module app"}
)public final class PayServiceManager {   public static final PayServiceManager INSTANCE;   static {
      PayServiceManager var0 = new PayServiceManager();
      INSTANCE = var0;
   }
}

通过以上代码,我们了解事实就是这个样子的,使用Kotlin"object"进行对象声明与我们的饿汉式单例的代码基本是相同的。

2. 双重校验懒汉式

//java 代码
 private PayManager(){

   }   private  volatile static PayManager payManager;    public static  PayManager getPayManager() {        if(payManager == null){            synchronized (PayManager.class){                if(payManager == null){
                    payManager = new PayManager()
                }
            }
        }        return payManager;
    }
//kotlin实现class PayServiceManager private constructor() {
    companion object {
        val instance: PayServiceManager by lazy {
            PayServiceManager()
        }
    }
}
  • 显式声明构造方法为private

  • companion object用来在class内部声明一个对象

  • PayServiceManager的实例instance 通过lazy来实现懒汉式加载

  • lazy默认情况下是线程安全的,这就可以避免多个线程同时访问生成多个实例的问题

知识点:

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

  • 默认情况下,对于 lazy 属性的求值是同步锁的(synchronized):该值只在一个线程中计算,并且所有线程会看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。 而如果你确定初始化将总是发生在单个线程,那么你可以使用 LazyThreadSafetyMode.NONE 模式, 它不会有任何线程安全的保证以及相关的开销。
    有兴趣可参考:lazy讲解

3. 静态内部类式

//Java实现private PayManager(){

   }   private static class PayManagerHolder{
       private static PayManager payManager = new PayManager();
   }   public static PayManager getPayManager(){       return PayManagerHolder.payManager;
   }
//kotlin实现class PayServiceManager private constructor() {
    companion object {
        val instance =PayServiceManagerHolder.payServiceManager
    }    private object PayServiceManagerHolder {
        val payServiceManager = PayServiceManager()
    }
}



作者:遛狗的程序员
链接:https://www.jianshu.com/p/2205bc889b8d


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消