kotlin委托代理

Quibbler 4月前 180

kotlin委托代理


        设计模式中有个委托模式(即代理模式),kotlin中的委托可以通过by关键字实现。

        

1、接口委托

        如何用Kotlin实现一个接口委托呢?举个例子,有一个接口:

    interface IProxy {
        fun handle()
    }

        普通方式,先实现这个接口:

    class ProxyImp : IProxy {
        override fun handle() {
        }
    }

        在用代理类封装一下:

    class ProxyBase(private val proxy: IProxy) : IProxy {
        override fun handle() {
            proxy.handle()
        }
    }

        换成Kotlin,仅需一个by关键字即可:

    //用该实例代理
    class ProxyBase : IProxy by ProxyImp()

    //使用传入的参数代理
    class ProxyBase(private val proxy: IProxy) : IProxy by proxy


        

2、属性委托

        属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。

    val/var <属性名>: <类型> by <表达式>


        

3、延迟委托

        使用by lazy延迟加载,是Kotlin提供的一种懒加载技术,代码块中的代码并不会在一开始就执行,只有在使用时才会进行初始化值,一般和依赖注入配合使用。

        使用也很简单,例如字符串变量的延迟加载:

    val name: String by lazy {
        "Quibbler"
    }

        查看对应的Java代码如下:

   @NotNull
   private static final Lazy name$delegate;
   
   @NotNull
   public static final String getName() {
      Lazy var0 = name$delegate;
      Object var1 = null;
      Object var2 = null;
      return (String)var0.getValue();
   }
   
   static {
      name$delegate = LazyKt.lazy((Function0)null.INSTANCE);
   }

        从Kotlin源码角度看Lazy的实现逻辑:

    public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
    
    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 instance
        private val lock = lock ?: this
        
        override val value: T
            get() {
                val _v1 = _value
                if (_v1 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST")
                    return _v1 as T
                }
                return synchronized(lock) {
                    val _v2 = _value
                    if (_v2 !== UNINITIALIZED_VALUE) {
                        @Suppress("UNCHECKED_CAST") (_v2 as T)
                    } else {
                        val typedValue = initializer!!()
                        _value = typedValue
                        initializer = null
                        typedValue
                    }
                }
            }
            
        override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
        
        override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
        
        private fun writeReplace(): Any = InitializedLazyImpl(value)
    }

        从源码中不难看出原理基本逻辑:

  • 默认为SynchronizedLazyImpl实现,initializer是lambda表达式,比如最上面的Lazy的lambda为{"Quibbler"}
  • 默认值赋值为UNINITIALIZED_VALUE,如果不为默认值则直接返回,说明已经赋值过了。
  • 后面的赋值方法由Synchronized包裹,支持多线程访问,先检查是否为UNINITIALIZED_VALUE,不为默认值直接返回
  • 未赋值过,先执行initializer,返回值赋值给typedValue,同时initializer = null,然后返回结果value


不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com