委託
委託模式是軟件設計模式中的一項基本技巧。
在委託模式中,有兩個對象參與處理同一個請求,接受請求的對象將請求委託給另一個對象來處理。
委託模式是一項基本技巧,許多其他的模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了委託模式
使用java舉例:
class RealPrinter { // the "delegate"
void print() {
System.out.print("something");
}
}
class Printer { // the "delegator"
RealPrinter p = new RealPrinter(); // create the delegate
void print() {
p.print(); // delegation
}
}
public class Main {
// to the outside world it looks like Printer actually prints.
public static void main(String[] args) {
Printer printer = new Printer();
printer.print();
}
}
可以看到代碼中printer 最終其實調用了RealPrinter的方法。
委託模式已經被證明是實現繼承的一個很好的替代方式,在擴展一個基類並且重寫方法時,基類就必須依賴子類的實現,當不斷地修改的時候,基類就會失去當初的性質,Kotlin中就將類默認爲final,確保不會被修改。
Kotlin中實現委託比較方便,Kotlin 通過關鍵字 by 實現委託。
類委託
類的委託即一個類中定義的方法實際是調用另一個類的對象的方法來實現的。
實際例子:
默認實現的代碼:
class DefaultCollection<T> : MutableCollection<T> {
private val innerList = mutableListOf<T>()
private var addedSum = 0
override fun add(element: T): Boolean {
addedSum++
return innerList.add(element)
}
override fun addAll(elements: Collection<T>): Boolean {
addedSum += elements.size
return innerList.addAll(elements)
}
override val size: Int
get() = innerList.size
override fun contains(element: T): Boolean = innerList.contains(element)
override fun containsAll(elements: Collection<T>): Boolean = innerList.addAll(elements)
override fun isEmpty(): Boolean = innerList.isEmpty()
override fun iterator(): MutableIterator<T> = innerList.iterator()
override fun clear() = innerList.clear()
override fun remove(element: T): Boolean = innerList.remove(element)
override fun removeAll(elements: Collection<T>): Boolean = innerList.removeAll(elements)
override fun retainAll(elements: Collection<T>): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
通過委託實現的代碼:
class DelegatingCollection3<T>(private val innerList: MutableCollection<T> = HashSet<T>()) : MutableCollection<T> by innerList {
private var addedSum = 0
override fun add(element: T): Boolean {
addedSum++
return innerList.add(element)
}
override fun addAll(elements: Collection<T>): Boolean {
addedSum += elements.size
return innerList.addAll(elements)
}
}
屬性委託
屬性委託指的是一個類的某個屬性值不是在類中直接進行定義,而是將其託付給一個代理類,從而實現對該類的屬性統一管理。
屬性委託語法格式:
val/var <屬性名>: <類型> by <表達式>
- var/val:屬性類型(可變/只讀)
- 屬性名:屬性名稱
- 類型:屬性的數據類型
- 表達式:委託代理類
by 關鍵字之後的表達式就是委託, 屬性的 get() 方法(以及set() 方法)將被委託給這個對象的 getValue() 和 setValue() 方法。屬性委託不必實現任何接口, 但必須提供 getValue() 函數(對於 var屬性,還需要 setValue() 函數)。
import kotlin.reflect.KProperty
// 定義包含屬性委託的類
class Example {
var p: String by Delegate()
}
// 委託的類
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 這裏委託了 ${property.name} 屬性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 屬性賦值爲 $value")
}
}
fun main(args: Array<String>) {
val e = Example()
println(e.p) // 訪問該屬性,調用 getValue() 函數
e.p = "Runoob" // 調用 setValue() 函數
println(e.p)
}