Kotlin 更加优雅的 Builder - 理解 with

引言

在 Android 开发过程中,我们经常需要对一个组件进行多个参数的自定义,但是如果单纯使用构造函数来实现是非常麻烦的:

public class Component {
    public Component(int id) {
    }

    public Component(String name) {
    }

    public Component(int id, String name) {
    }
}复制代码

可见,当参数一多,代码量急剧上升,而且调用的时候也很不好看。

有人说,我可以先把对象实例化出来之后在用 setter 设置各个参数啊。是的,那确实是一种很简单的 approach,但是这种结构不够紧凑,我们想要的是一块整体的代码或一句代码就完成实例化。

Builder 设计模式就是来解决这类问题的。

使用 Builder 后,我们在实例化组件的时候,可以像下面这样:

Component c = new Component.Builder()
                        .id(id)
                        .name(name)
                        .build()复制代码

代码结构更加清晰,而且参数的自定义更加灵活。

Java 的窘境

用 Java 写 Builder 有点一言难尽:

public class Component {
    private Builder mBuilder;
    private Component(Builder builder) {
        mBuilder = builder;
    }

    public static class Builder {
        private int id = 0;
        private String name = "xxx";

        public Builder id(int id) {
            this.id = id;
            return this;
        }

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Component build() {
            return new Component(this);
        }
    }
}复制代码

可以看到,虽然对于参数的自定义比直接用构造方法的方式灵活不少,但是我们需要创建静态内部类,而且写很多样板代码,这样开发的效率较低。

Kotlin 的曙光

Kotlin 作为新晋 Android 开发语言,其与 Java 的互操性和灵活性让人赞不绝口,我们看看她在 Builder 设计模式上能给我们带来什么。

首先,需要理解 with 方法:

inline fun <T, R> with(receiver: T, block: T.() -> R): R {...}复制代码

with 接受两个参数,第一个是 T 类型对象,第二个是该对象内部的一个方法,该方法返回一个 R 类型的对象。

也就是说,with 能调用一个 T 类型对象里面的方法来返回一个 R 类型对象。

比如我们有一个类:

class Paint() {
    var color = Color.WHITE

    fun drawPig() {
    }

    fun drawDog() {
    }

    fun getString(): String {
    }
}复制代码

那么我们可以像这样调用:

val string = with(Paint(), {     //看不懂这部分写法的请先了解一哈 kotlin 的 lambda 表达式
                color = Color.BLACK
                drawDog()
                color = Color.PINK
                drawPig()
                getString()     //最后一个语句的返回值为整个方法的返回值
            })复制代码

相当于,我们创建了一个 Paint 对象,并对调用了该对象的各种方法(或者修改成员变量)。也就是说,直接在 {} 里面营造 Paint 类的环境,使 Paint 对象的方法和成员变量可以直接访问。

上面整块代码相当于:

val paint = Paint()
val string = with(paint) {      
    paint.color = Color.BLACK
    paint.drawDog()
    paint.color = Color.PINK
    paint.drawPig()
    paint.getString()       //作为返回值返回
}复制代码

下一篇文章中,我们将使用 with 来打造 Builder

———

技术上的问题,欢迎讨论。

最近在 Github 上维护的项目:

  • LiteWeather [一款用 Kotlin 编写,基于 MD 风格的轻量天气 App],对使用 Kotlin 进行实际开发感兴趣的同学可以看看,项目中会使用到 Kotlin 的委托机制、扩展机制和各种新奇的玩意。
  • LiteReader [一款基于 MD 的极轻阅读 App,提供知乎日报、豆瓣电影等资源],项目主要使用了 MVVM 设计模式,界面遵循 Material Design 规范,提供轻量的阅读体验。
  • LiveMVVM [Kotlin 编写的 Android MVVM 框架,基于 android-architecture],轻量 MVVM+Databinding 开发框架。
  • AnkoUtil [Kotlin 编写的 Android 扩展库]

欢迎 star/fork/follow 提 issue 和 PR。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值