正文开始
我认为Kotlin的委托与组合模式(composition pattern)相当接近,所以在认识委托前,先来回顾一下Java的组合模式吧!
组合模式小Demo
interface Animal {
fun feed ()
}
class Dog : Animal {
override fun feed () {
println ( " 吃狗粮 " )
}
}
class Cat : Animal {
override fun feed () {
println ( " 吃猫粮 " )
}
}
class AnimalHost ( val animal : Animal ) {
fun feed () {
animal.feed()
}
}
fun main ( args : Array < String >) {
val dog = Dog ()
val dogHost = AnimalHost (dog)
animalHost.feed()
// 吃狗粮
val cat = Cat ()
val catHost = AnimalHost (cat)
catHost.feed()
// 吃猫粮
}
俗话说:
「多用组合,少用继承。」
我记得这是在深入浅出设计模式这本书中出现过的警语,虽然继承是物件导向的重点之一,但过多的继承反而会让程式码难以维护……(真是难以体会呀?)
总之你会因为各种不同的需求,去创造不同的子类别,并且覆写相关的方法。当类别属性变多,你要覆写的就会变多;当有几个子类别中大部分的属性都相同,你还是需要多创造几个子类别,然后疯狂的覆写。
使用委托实作
使用组合模式时,当你要启动执行者的方法时,还是得依赖执行者的类别方法;换句话说,执行的方法需要被呼叫,执行者方法才会被呼叫。 在Kotlin中使用委托就不一样了,你可以直接去执行方法:
interface Animal {
fun feed ()
}
class Dog : Animal {
override fun feed () {
println ( " 吃狗粮 " )
}
}
class Cat : Animal {
override fun feed () {
println ( " 吃猫粮 " )
}
}
class AnimalHost ( animal : Animal ) : Animal by animal
fun main ( args : Array < String >) {
val dog = Dog ()
val dogHost = AnimalHost (dog)
animalHost.feed()
// 吃狗粮
val cat = Cat ()
val catHost = AnimalHost (cat)
catHost.feed()
// 吃猫粮
}
上述代码AnimalHost没有任何代码但他实际上委托了animal的所有属性和方法,所以你调用Animal类的feed的方法时相当于调用你传入的介质的方法,会委托给你传入的介质的方法。
在kotlin中还支持多个委托代码如下:
interface Clothes {
fun wearClothes ()
}
interface Shoes {
fun wearShoes ()
}
class Jack : Clothes {
override fun wearClothes () {
println ( " 穿夹克 " )
}
}
class Sweater : Clothes {
override fun wearClothes () {
println ( " 穿毛衣 " )
}
}
class Leather : Shoes {
override fun wearShoes () {
println ( " 穿皮鞋 " )
}
}
class Sports : Shoes {
override fun wearShoes () {
println ( " 穿运动鞋 " )
}
}
class Person ( clothes : Clothes , shoes : Shoes ) : Clothes by clothes, Shoes by shoes
fun main ( args : Array < String >) {
val jack = Jack ()
val leather = Leather ()
val man = Person (jack, leather)
man.wearClothes()
man.wearShoes()
val sweater = Sweater ()
val sports = Sports ()
val man2 = Person (sweater, sports)
man2.wearClothes()
man2.wearShoes()
}