如何在Kotlin中实现Builder模式? [英] How to implement Builder pattern in Kotlin?

查看:978
本文介绍了如何在Kotlin中实现Builder模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Kotlin世界的新手。我喜欢我到目前为止看到的,并开始考虑将我们在Java应用程序中使用的一些图书馆转换为Kotlin。



这些图书馆充满了Pojos与设定者,getter和Builder类。现在我已经google了,找到什么是在Kotlin中实现Builders的最好方法,但没有成功。



第二次更新:问题是如何编写一个Builder设计模式在科特林有一些参数的简单pojo?下面的代码是我尝试编写java代码,然后使用eclipse-kotlin-plugin转换为Kotlin。

  class Car私有构造函数(builder:Car.Builder){
var model:String? = null
var year:Int = 0
init {
this.model = builder.model
this.year = builder.year
}
伴侣对象生成器{
var model:String? = null
private set

var year:Int = 0
private set

fun model(model:String):Builder {
this.model = model
return this
}
fun year(year:Int):Builder {
this.year = year
return this
}
fun build():Car {
val car = Car(this)
return car
}
}
}


解决方案

首先,在大多数情况下,您不需要在Kotlin中使用构建器,因为我们有默认和命名参数。这可以让你编写

  class Car(val model:String?= null,val year:Int = 0)

,使用如下:

  val car = Car(model =X)

如果你绝对想使用构建器,以下是如何实现的:



使Builder成为协同对象没有意义因为对象是单例。而是将其声明为一个嵌套类(默认情况下在Kotlin中是静态的)。



将属性移动到构造函数,以便对象也可以以常规方式实例化构造函数private(如果不应该),并使用辅助构造函数,该构造函数接受构建器并委托给主构造函数。代码如下所示:

  class Car(//如果需要,添加私有构造函数
val model:String? ,
val年:Int
){

私有构造函数(builder:Builder):这个(builder.model,builder.year)

类Builder {
var model:String? = null
private set

var year:Int = 0
private set

fun model(model:String)= apply {this.model =模型}

fun年(年:Int)=申请{this.year =年}

fun build()= Car(this)
}
}

用法: val car = Car.Builder()。 (X)。builder()



此代码可以通过使用构建器DSL

  class Car(
val model:String?
val year:Int
){

private constructor(builder:Builder) model,builder.year)

companion object {
inline fun build(block:Builder。() - > Unit)= Builder()。apply(block).build()
}

class Builder {
var model:String? = null
var year:Int = 0

fun build()= Car(this)
}
}

用法: val car = Car.build {model =X}



如果需要某些值并且没有默认值,则需要将它们放在构建器的构造函数中,还可以在 build 方法我们刚刚定义:

  class Car(
val model:String?
val年:Int,
val required:String
){

私有构造函数(builder:Builder):这个(builder.model,builder.year,builder.required)

伴随对象{
inline fun build(required:String,block:Builder。() - > Unit)= Builder(必需).apply(block).build()


class Builder(
val required:String
){
var model:String? = null
var year:Int = 0

fun build()= Car(this)
}
}

用法: val car = Car.build(required =requiredValue){model =X}


Hi I am a newbie in the Kotlin world. I like what I see so far and started to think to convert some of our libraries we use in our application from Java to Kotlin.

These libraries are full of Pojos with setters, getters and Builder classes. Now I have googled to find what is the best way to implement Builders in Kotlin but no success.

2nd Update: The question is how to write a Builder design-pattern for a simple pojo with some parameters in Kotlin? The code below is my attempt by writing java code and then using the eclipse-kotlin-plugin to convert to Kotlin.

class Car private constructor(builder:Car.Builder) {
    var model:String? = null
    var year:Int = 0
    init {
        this.model = builder.model
        this.year = builder.year
    }
    companion object Builder {
        var model:String? = null
        private set

        var year:Int = 0
        private set

        fun model(model:String):Builder {
            this.model = model
            return this
        }
        fun year(year:Int):Builder {
            this.year = year
            return this
        }
        fun build():Car {
            val car = Car(this)
            return car
        }
    }
}

解决方案

First and foremost, in most cases you don't need to use builders in Kotlin because we have default and named arguments. This enables you to write

class Car(val model: String? = null, val year: Int = 0)

and use it like so:

val car = Car(model = "X")

If you absolutely want to use builders, here's how you could do it:

Making the Builder a companion object doesn't make sense because objects are singletons. Instead declare it as an nested class (which is static by default in Kotlin).

Move the properties to the constructor so the object can also be instantiated the regular way (make the constructor private if it shouldn't) and use a secondary constructor that takes a builder and delegates to the primary constructor. The code will look as follow:

class Car( //add private constructor if necessary
        val model: String?,
        val year: Int
) {

    private constructor(builder: Builder) : this(builder.model, builder.year)

    class Builder {
        var model: String? = null
            private set

        var year: Int = 0
            private set

        fun model(model: String) = apply { this.model = model }

        fun year(year: Int) = apply { this.year = year }

        fun build() = Car(this)
    }
}

Usage: val car = Car.Builder().model("X").builder()

This code can be shortened additionally by using a builder DSL:

class Car (
        val model: String?,
        val year: Int
) {

    private constructor(builder: Builder) : this(builder.model, builder.year)

    companion object {
        inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build()
    }

    class Builder {
        var model: String? = null
        var year: Int = 0

        fun build() = Car(this)
    }
}

Usage: val car = Car.build { model = "X" }

If some values are required and don't have default values, you need to put them in the constructor of the builder and also in the build method we just defined:

class Car (
        val model: String?,
        val year: Int,
        val required: String
) {

    private constructor(builder: Builder) : this(builder.model, builder.year, builder.required)

    companion object {
        inline fun build(required: String, block: Builder.() -> Unit) = Builder(required).apply(block).build()
    }

    class Builder(
            val required: String
    ) {
        var model: String? = null
        var year: Int = 0

        fun build() = Car(this)
    }
}

Usage: val car = Car.build(required = "requiredValue") { model = "X" }

这篇关于如何在Kotlin中实现Builder模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆