Kotlin委托模式入门

1.委托模式

委托模式是软件设计模式中的一项基本技巧。简单来说,委托就是接收请求的一方将实现委托给了另一方,在Kotlin的语法结构中,使用by关键字可以直接支持委托模式,不需要编写样板代码。by关键字可以用在类和属性当中,分别表示类委托属性委托

2.类委托

先看一个java中使用委托模式的例子:

    interface Printer {
        void printSomething(String something);
    }


    static class PrinterDelegate implements Printer {

        @Override
        public void printSomething(String something) {
            System.out.println("print from Delegate:" + something);
        }
    }

    static class PrintingHouse implements Printer {

        Printer mPrinter;

        public PrintingHouse(Printer printer) {
            mPrinter = printer;
        }

        @Override
        public void printSomething(String something) {
            mPrinter.printSomething(something);
        }
    }

    public static void main(String[] args) {
    
        PrinterDelegate delegate = new PrinterDelegate();
        PrintingHouse printingHouse = new PrintingHouse(delegate);
        printingHouse.printSomething("newspaper");
        
    }


//输出结果
//print from Delegate:newspaper

PrintingHouse实现了Printer接口,但PrintingHouse并没有具体实现printSomething的功能,而是委托给了PrinterDelegate去实现,接下来我们使用kotlin的方式去实现它:


interface Printer{
    fun printSomething(something:String)
}

class PrinterDelegate : Printer{

    override fun printSomething(something: String) {
        println("print from Delegate : $something")
    }

}

class PrintingHouse(printer:Printer) : Printer by printer

fun main(){

    val delegate = PrinterDelegate()
    val printingHouse = PrintingHouse(delegate)
    printingHouse.printSomething("newspaper")

}

//输出结果
//print from Delegate:newspaper
```**
两个版本实现的功能相同,可以看到kotlin完成委托仅需要使用by**关键字,这种写法就是kotlin中的类委托,类委托的声明直接写在类声明表达式中,就像这样:

```kotlin
interface A
interface B
class C(a:A,b:B) : A by a,B by b

3.属性委托

属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是委托给一个代理类,从而实现对该属性统一管理,语法如下:

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

by关键字之后的表达式就是委托, 属性的 get() 方法(以及set() 方法)将被委托给这个对象的 getValue() 和 setValue() 方法。受委托的对象需提供 getValue() 函数(对于 var属性,还需要 setValue() 函数)。

看下面一个例子,定义一个Student类,将name属性委托给NameDelegate :

class Student {

    var name: String by NameDelegate()

}

class NameDelegate {

    private var value: String = ""

    operator fun getValue(thisRef: Student, property: KProperty<*>): String {
        return if (value.isEmpty()) "unknown" else value
    }

    operator fun setValue(thisRef: Student, property: KProperty<*>, value: String) {
        this.value = value.trim()
    }

}

fun main() {

    val xiaoMing = Student()
    println(xiaoMing.name)

    xiaoMing.name = "  小明    "
    println(xiaoMing.name)

}

//输出结果
//unknown
//小明

虽然受委托的类没有要求实现任何接口,但如果不想每次手动的去写getVlaue()和setValue()方法,也可以去实现ReadWriteProperty接口:

class NameDelegate : ReadWriteProperty<Student, String> {

    private var value: String = ""

    override fun getValue(thisRef: Student, property: KProperty<*>): String {
        return if (value.isEmpty()) "unknown" else value
    }

    override fun setValue(thisRef: Student, property: KProperty<*>, value: String) {
        this.value = value.trim()
    }

}

实际上,Kotlin 的标准库中已经内置了很多工厂方法来实现属性的委托,在Android开发过程中经常用到的lazy就是标准库中的委托,lazy() 是接受一个 lambda 并返回一个 Lazy 实例的函数。lazy表示延迟属性,其值只在首次访问时计算。

这是lazy的一个使用示例:

class MainActivity : AppCompatActivity() {

    private val mDialog : Dialog by lazy {
        AlertDialog.Builder(this)
            .setTitle("I am title")
            .setNegativeButton("confirm",null)
            .create()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }


    fun showDialog(view: View) {
        mDialog.show()
    }

}

该示例中,点击Button展示一个对话框mDialog,mDialog只在使用的时候才进行初始化。

4.总结

使用委托很大的一个好处是可以节省很多样板代码的编写,例如,你可以通过代理类在Activity中完成Extra或者SharedPreference属性的初始化。委托还有更多的案例,详细请参考官方文档。

更多安卓知识体系,请关注公众号:
三分钟Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值