Kotlin 使用一些常量和其他变量创建生成器

Kotlin 使用一些常量和其他变量创建生成器,kotlin,Kotlin,我有以下课程,不确定这是否是创建生成器的最佳设计。基本上,销售和产品将有不同的图标和背景常数。但是标题和描述可以更改。可以添加其他常数,即技术常数。所以这个类的用户不必担心这些常量是如何创建的 但是标题和地址需要在课堂之外提供。在创建我的生成器时,我使用了副本来更新标题和说明。不确定这是不是最好的方法 kotlin 1.3.61 我是这样使用它的: class Marketing { data class Model( val title: String = "",

我有以下课程,不确定这是否是创建生成器的最佳设计。基本上,销售和产品将有不同的图标和背景常数。但是标题和描述可以更改。可以添加其他常数,即技术常数。所以这个类的用户不必担心这些常量是如何创建的

但是标题和地址需要在课堂之外提供。在创建我的生成器时,我使用了
副本
来更新标题和说明。不确定这是不是最好的方法

kotlin 1.3.61
我是这样使用它的:

class Marketing {
    data class Model(
        val title: String = "",
        val description: String = "",
        val icon: Int,
        val background: Int)

    class Builder() {
        private var title: String = ""
        private var description: String = ""

        private val PRODUCT = Model(
            icon = 111111,
            background = 333333)

        private val SALES = Model(
            icon = 222222,
            background = 444444)

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

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

        fun buildProduct(): Model {
            return PRODUCT.copy(title = title, description = description)
        }

        fun buildSales(): Model {
            return SALES.copy(title = title, description = description)
        }
    }
}
data class Model(
    val title: String,
    val description: String,
    val icon: Int,
    val background: Int)

class Builder() {
    data class ModelTemplate(val icon: Int, val background: Int) {
        // optionally check that title and description aren't empty, or are valid in some other way
        fun build(title: String, description: String) = Model(icon, background, title, description)
    }

    private val product = ModelTemplate(icon = 111111, background = 333333)
    private val sales = ModelTemplate(icon = 222222, background = 444444)

    private var title: String = ""
    private var description: String = ""

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

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

    fun buildProduct(): Model {
        return product.build(title = title, description = description)
    }

    fun buildSales(): Model {
        return sales.build(title = title, description = description)
    }
}
正如您所见,通过调用适当的构建器(即
buildProduct()
buildSales()


非常感谢您提供的任何建议,让这一切变得更好

我真的不明白为什么它不仅仅是两种方法:

val product = Marketing.Builder()
    .description("this is the description of the product")
    .title("this is the title of the product")
    .buildProduct()

val sales = Marketing.Builder()
    .description("this is the description of the sales")
    .title("this is the title of the sales")
    .buildSales()
或许

fun buildProduct(title: String, description: String): Model {
    return Model(icon = 111111, background = 333333, title = title, description = description)
}

fun buildSales(title: String, description: String): Model {
    return Model(icon = 222222, background = 444444, title = title, description = description)
}
如果您希望始终命名
title
description
,那么它看起来不像是一个标题和描述为空的
模型,实际上很有用(是吗?),因此我会添加一个额外的类,而不是使它们成为默认参数

class Builder(private val title: String, private val description: String) {
    fun buildProduct(): Model {
        return Model(icon = 111111, background = 333333, title = title, description = description)
    }

    fun buildSales(): Model {
        return Model(icon = 222222, background = 444444, title = title, description = description)
    }
}

可以考虑使用<代码>密封< /COD>此类类:

class Marketing {
    data class Model(
        val title: String = "",
        val description: String = "",
        val icon: Int,
        val background: Int)

    class Builder() {
        private var title: String = ""
        private var description: String = ""

        private val PRODUCT = Model(
            icon = 111111,
            background = 333333)

        private val SALES = Model(
            icon = 222222,
            background = 444444)

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

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

        fun buildProduct(): Model {
            return PRODUCT.copy(title = title, description = description)
        }

        fun buildSales(): Model {
            return SALES.copy(title = title, description = description)
        }
    }
}
data class Model(
    val title: String,
    val description: String,
    val icon: Int,
    val background: Int)

class Builder() {
    data class ModelTemplate(val icon: Int, val background: Int) {
        // optionally check that title and description aren't empty, or are valid in some other way
        fun build(title: String, description: String) = Model(icon, background, title, description)
    }

    private val product = ModelTemplate(icon = 111111, background = 333333)
    private val sales = ModelTemplate(icon = 222222, background = 444444)

    private var title: String = ""
    private var description: String = ""

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

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

    fun buildProduct(): Model {
        return product.build(title = title, description = description)
    }

    fun buildSales(): Model {
        return sales.build(title = title, description = description)
    }
}
这样:

  • 您有统一的类型(即相同的超类,因此您可以使用相同的类型(
    模型
    )传递它们)
  • 您可以为所有这些功能提供不同和/或通用的功能
优点:

您可以将实例作为
Model
传递,并将所有实例视为相同的实例,和/或在when子句中检查它们,以确定要操作的正确类型(如果用作表达式,则不需要else分支):

或者你可以:

fun showModel(model: Model){
    title.text = model.title
}

您可以阅读有关密封类的更多信息。

我想说的是,使用单个生成器构建多个类型是不安全的。最好将它划分为特定的类,可能有一些共享的基类。因此,我的答案是:

模型类

fun doSomething(model: Model) = when (model) {
    is Product -> Unit
    is Sales -> Unit
}
open class BaseModel(val icon: Int, val background: Int)
class ProductModel(val title: String, val description: String, icon: Int, background: Int) : BaseModel(icon, background)
class SalesModel(val title: String, val description: String, icon: Int, background: Int) : BaseModel(icon, background)
abstract class BaseBuilder<T : BaseModel> {
    abstract var icon: Int
    abstract var background: Int

    abstract fun build(): T
}

class ProductBuilder : BaseBuilder<ProductModel>() {
    override var icon = 222222
    override var background = 444444
    var title = ""
    var description = ""

    override fun build() = ProductModel(title, description, icon, background)
}

class SalesBuilder : BaseBuilder<SalesModel>() {
    override var icon = 111111
    override var background = 333333
    var title = ""
    var description = ""

    override fun build() = SalesModel(title, description, icon, background)
}
建筑商

fun doSomething(model: Model) = when (model) {
    is Product -> Unit
    is Sales -> Unit
}
open class BaseModel(val icon: Int, val background: Int)
class ProductModel(val title: String, val description: String, icon: Int, background: Int) : BaseModel(icon, background)
class SalesModel(val title: String, val description: String, icon: Int, background: Int) : BaseModel(icon, background)
abstract class BaseBuilder<T : BaseModel> {
    abstract var icon: Int
    abstract var background: Int

    abstract fun build(): T
}

class ProductBuilder : BaseBuilder<ProductModel>() {
    override var icon = 222222
    override var background = 444444
    var title = ""
    var description = ""

    override fun build() = ProductModel(title, description, icon, background)
}

class SalesBuilder : BaseBuilder<SalesModel>() {
    override var icon = 111111
    override var background = 333333
    var title = ""
    var description = ""

    override fun build() = SalesModel(title, description, icon, background)
}
通过这种方式,您可以轻松安全地创建模型:

class Marketing {
    companion object {
        fun buildProduct(filler: ProductBuilder.() -> Unit) : ProductModel {
            return ProductBuilder().run {
                filler()
                build()
            }
        }
        fun buildSales(filler: SalesBuilder.() -> Unit) : SalesModel {
            return SalesBuilder().run {
                filler()
                build()
            }
        }
    }
}
必填字段

如果要使某些属性不可分支,可以将其从
var
属性替换为
val
构造函数。
标题
属性示例:

Builder

val product = Marketing.buildProduct {
    title = "title"
    description = "descr"
}
使用

class ProductBuilder(val title: String) : BaseBuilder<ProductModel>() {
    override var icon = 111111
    override var background = 333333

    var description = ""

    override fun build() = ProductModel(title, description, icon, background)
}
fun buildProduct(title: String, filler: ProductBuilder.() -> Unit) : ProductModel {
    return ProductBuilder(title).run {
        filler()
        build()
    }
}

您是否真的需要模仿默认的Java Builder方法,即使用函数而不是属性访问方式?我喜欢这个答案。但是你能解释一下统一类型的含义吗Thanks@ant2009是的,当然。我将编辑我的帖子,并添加一些解释。太好了,谢谢回答。但我确实喜欢密封类实现