1 委托模式简介
委托模式的类图结构如下。
对应的 Kotlin 代码如下。
fun main() {
var baseImpl = BaseImpl()
var baseWrapper = BaseWrapper(baseImpl)
baseWrapper.myFun1() // 打印: BaseImpl, myFun1
baseWrapper.myFun2() // 打印: BaseImpl, myFun2
}
interface Base {
fun myFun1()
fun myFun2()
}
class BaseWrapper(var baseImpl: Base): Base {
override fun myFun1() {
baseImpl.myFun1()
}
override fun myFun2() {
baseImpl.myFun2()
}
}
class BaseImpl: Base {
override fun myFun1() {
println("BaseImpl, myFun1")
}
override fun myFun2() {
println("BaseImpl, myFun2")
}
}
2 类委托
Kotlin 可以简化 BaseWrapper,简化后的代码如下。
fun main() {
var baseImpl = BaseImpl()
var baseWrapper = BaseWrapper(baseImpl)
baseWrapper.myFun1() // 打印: BaseImpl, myFun1
baseWrapper.myFun2() // 打印: BaseImpl, myFun2
}
interface Base {
fun myFun1()
fun myFun2()
}
class BaseWrapper(var baseImpl: Base): Base by baseImpl
class BaseImpl: Base {
override fun myFun1() {
println("BaseImpl, myFun1")
}
override fun myFun2() {
println("BaseImpl, myFun2")
}
}
3 属性委托
3.1 by T
import kotlin.reflect.KProperty
fun main() {
var str: String by StringDelegate()
str = "abc"
println(str)
}
class StringDelegate {
var value: String? = null
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("getValue, thisRef=$thisRef, name=${property.name}, value=$value")
return value ?: throw IllegalStateException("Property not initialized")
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("setValue, thisRef=$thisRef, name=${property.name}, value=$value")
this.value = value
}
}
打印日志如下。
setValue, thisRef=null, name=str, value=ABC
getValue, thisRef=null, name=str, value=ABC
ABC
3.2 by lazy
fun main() {
// lazy为生成的委托对象, 获取属性时会执行lazy里面的操作, 只支持val变量
val str: String by lazy { "666" }
println(str) // 打印: 666
}
3.3 by Delegates.observable
fun main() {
var str: String by Delegates.observable("666") { prop, old, new ->
println("prop=$prop, old=$old, new=$new")
}
println(str) // 666
// prop=property str (Kotlin reflection is not available), old=666, new=888
str = "888"
}
3.4 by ::T
fun main() {
var example = Example("ABC")
example.str2 = "DEF"
// str1=DEF, str2=DEF
println("str1=${example.str1}, str2=${example.str2}")
}
class Example(var str1: String) {
var str2: String by ::str1
}
说明:属性被委托后,str1 和 str2 同时修改。
3.5 by map
fun main() {
var map: MutableMap<String, Any> = mutableMapOf(
"name" to "Tom",
"age" to 23,
"id" to 1001
)
var user = User(map)
println(user) // (Tom, 23, 1001)
}
class User(map: MutableMap<String, Any>) {
var name: String by map
var age: Int by map
var id: Int by map
override fun toString(): String = "($name, $age, $id)"
}