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
精彩的人生需要浪漫、无畏和勇气。