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

这些库充满了带有setter、getter和Builder类的pojo。现在我已经在谷歌上找到了在Kotlin中实现Builders的最佳方法,但没有成功。

第二次更新:问题是如何写一个建设者设计模式的一个简单的pojo与一些参数在Kotlin?下面的代码是我尝试编写java代码,然后使用eclipse-kotlin-plugin转换为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
        }
    }
}

当前回答

上面的答案有一点改变和改进

class MyDialog {
  private var title: String? = null
  private var content: String? = null
  private var confirmButtonTitle: String? = null
  private var rejectButtonTitle: String? = null

  @DrawableRes
  private var icon: Int? = null


  fun show() {
    // set dialog content here and show at the end
  }

  class Builder {
      private var dialog: MyDialog = MyDialog()

      fun title(title: String) = apply { dialog.title = title }

      fun icon(@DrawableRes icon: Int) = apply { dialog.icon = icon }

      fun content(content: String) = apply { dialog.content = content }

      fun confirmTitle(confirmTitle: String) = apply { dialog.confirmButtonTitle = confirmTitle }

      fun rejectButtonTitle(rejectButtonTitle: String) = apply { dialog.rejectButtonTitle = rejectButtonTitle }

      fun build() = dialog
  }
}

和使用

MyDialog.Builder()
        .title("My Title")
        .content("My content here")
        .icon(R.drawable.bg_edittext)
        .confirmTitle("Accept")
        .rejectButtonTitle("Cancel")
        .build()
        .show()

其他回答

class Foo private constructor(@DrawableRes requiredImageRes: Int, optionalTitle: String?) {

    @DrawableRes
    @get:DrawableRes
    val requiredImageRes: Int

    val optionalTitle: String?

    init {
        this.requiredImageRes = requiredImageRes
        this.requiredImageRes = optionalTitle
    }

    class Builder {

        @DrawableRes
        private var requiredImageRes: Int = -1

        private var optionalTitle: String? = null

        fun requiredImageRes(@DrawableRes imageRes: Int): Builder {
            this.intent = intent
            return this
        } 

        fun optionalTitle(title: String): Builder {
            this.optionalTitle = title
            return this
        }

        fun build(): Foo {
            if(requiredImageRes == -1) {
                throw IllegalStateException("No image res provided")
            }
            return Foo(this.requiredImageRes, this.optionalTitle)
        }

    }

}

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

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

像这样使用它:

val car = Car(model = "X")

如果你绝对想要使用构建器,你可以这样做:

将Builder作为伴生对象没有意义,因为对象是单例对象。相反,将其声明为一个嵌套类(在Kotlin中默认是静态的)。

将属性移动到构造函数中,这样对象也可以以常规方式实例化(如果不应该,则将构造函数设置为私有),并使用接受构造函数并将其委托给主构造函数的辅助构造函数。代码如下所示:

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)
    }
}

用法:val car = car . builder ().model("X").build()

这段代码可以通过使用构建器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)
    }
}

用法:val car = car。建立{模型= "X"}

如果某些值是必需的,并且没有默认值,你需要将它们放在构建器的构造函数中,也需要放在我们刚刚定义的构建方法中:

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)
    }
}

用法:val car = car。build(required = "requiredValue") {model = "X"}

一种方法是做以下事情:

class Car(
  val model: String?,
  val color: String?,
  val type: String?) {

    data class Builder(
      var model: String? = null,
      var color: String? = null,
      var type: String? = null) {

        fun model(model: String) = apply { this.model = model }
        fun color(color: String) = apply { this.color = color }
        fun type(type: String) = apply { this.type = type }
        fun build() = Car(model, color, type)
    }
}

使用示例:

val car = Car.Builder()
  .model("Ford Focus")
  .color("Black")
  .type("Type")
  .build()

我在Kotlin中实现了一个基本的Builder模式,代码如下:

data class DialogMessage(
        var title: String = "",
        var message: String = ""
) {


    class Builder( context: Context){


        private var context: Context = context
        private var title: String = ""
        private var message: String = ""

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

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

        fun build() = KeyoDialogMessage(
                title,
                message
        )

    }

    private lateinit var  dialog : Dialog

    fun show(){
        this.dialog= Dialog(context)
        .
        .
        .
        dialog.show()

    }

    fun hide(){
        if( this.dialog != null){
            this.dialog.dismiss()
        }
    }
}

最后

Java:

new DialogMessage.Builder( context )
       .title("Title")
       .message("Message")
       .build()
       .show();

科特林:

DialogMessage.Builder( context )
       .title("Title")
       .message("")
       .build()
       .show()

我迟到了。如果我必须在项目中使用Builder模式,我也遇到了同样的困境。后来,经过研究,我意识到这是完全不必要的,因为Kotlin已经提供了命名参数和默认参数。

如果你真的需要实施,Kirill Rakhman的答案是关于如何以最有效的方式实施的可靠答案。您可能会发现另一件有用的事情是https://www.baeldung.com/kotlin-builder-pattern,您可以将其与Java和Kotlin的实现进行比较和对比