写点什么

Kotlin 下的 5 种单例模式,一招教你看懂 Netty

用户头像
Android架构
关注
发布于: 刚刚

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


到这里,如果还是有很多小伙伴不是很相信一行代码就能解决这个功能,我们可以通过一下方式查看 Kotlin 的字节码。

查看 Kotlin 对应字节码


我们进入我们的 Android Studio(我的 Android Studio 3.0,如果你的编译器版本过低,请自动升级) 选择 Tools 工具栏,选择"Kotlin",选择“Show Kotlin Bytecode"


选择过后就会进入到下方界面:



点击"Decompile" 根据字节码得到以下代码


public final class SingletonDemo {public static final SingletonDemo INSTANCE;private SingletonDemo(){}static {SingletonDemo var0 = new SingletonDemo();INSTANCE = var0;}}


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

二、懒汉式

//Java 实现 public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}}//Kotlin 实现 class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}fun get(): SingletonDemo{//细心的小伙伴肯定发现了,这里不用 getInstance 作为为方法名,是因为在伴生对象声明时,内部已有 getInstance 方法,所以只能取其他名字 return instance!!}}}


上述代码中,我们可以发现在 Kotlin 实现中,我们让其主构造函数私有化并自定义了其属性访问器,其余内容大同小异。


  • 如果有小伙伴不清楚 Kotlin 构造函数的使用方式。请点击 - - - 构造函数

  • 不清楚 Kotlin 的属性与访问器,请点击 - - -属性和字段

三、线程安全的懒汉式

//Java 实现 public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static synchronized SingletonDemo getInstance(){//使用同步锁 if(instance==null){instance=new Singlet


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


onDemo();}return instance;}}//Kotlin 实现 class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}@Synchronizedfun get(): SingletonDemo{return instance!!}}


}


大家都知道在使用懒汉式会出现线程安全的问题,需要使用使用同步锁,在 Kotlin 中,如果你需要将方法声明为同步,需要添加**@Synchronized**注解。

四、双重校验锁式(Double Check)

//Java 实现 public class SingletonDemo {private volatile static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){synchronized (SingletonDemo.class){if(instance==null){instance=new SingletonDemo();}}}return instance;}}//kotlin 实现 class SingletonDemo private constructor() {companion object {val instance: SingletonDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {SingletonDemo() }}}


哇!小伙伴们惊喜不,感不感动啊。我们居然几行代码就实现了多行的 Java 代码。其中我们运用到了 Kotlin 的延迟属性 Lazy


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


这里还有有两个额外的知识点。


  • 高阶函数,高阶函数是将函数用作参数或返回值的函数(我很纠结我到底讲不讲,哎)。大家还是看这个 ---高阶函数

  • 委托属性


如果你了解以上知识点,我们直接来看 Lazy 的内部实现。

Lazy 内部实现

public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =when (mode) {LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)}


观察上述代码,因为我们传入的 mode = LazyThreadSafetyMode.SYNCHRONIZED, 那么会直接走 SynchronizedLazyImpl,我们继续观察 SynchronizedLazyImpl。

Lazy 接口

SynchronizedLazyImpl 实现了 Lazy 接口,Lazy 具体接口如下:


public interface Lazy<out T> {//当前实例化对象,一旦实例化后,该对象不会再改变 public val value: T//返回 true 表示,已经延迟实例化过了,false 表示,没有被实例化,//一旦方法返回 true,该方法会一直返回 true,且不会再继续实例化 public fun isInitialized(): Boolean}


继续查看 SynchronizedLazyImpl,具体实现如下:

SynchronizedLazyImpl 内部实现

private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {private var initializer: (() -> T)? = initializer@Volatile private var _value: Any? = UNINITIALIZED_VALUE// final field is required to enable safe publication of constructed instanceprivate val lock = lock ?: this


override val value: Tget() {val _v1 = _value

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Kotlin下的5种单例模式,一招教你看懂Netty