编写适当的 DSL

Writing proper DSL

我希望能够编写调用工厂方法来创建对象的实例,而不是直接调用构造函数。

我有一个名为 PersonFactory 的工厂,它实现了一个名为 getPresonTypeOne(name: String, age:Int, address: String) 的方法。 PersonTypeOne有3个成员变量,分别是nameageaddress。我希望能够编写一些调用 getPresonTypeOne 的东西来创建 PersonTypeOne 的实例,而不是直接调用 PersonTypeOne 构造函数。

我理想中的东西看起来像这样

class PersonTypeOne(
      val name: String, 
      val age: Int, 
      val address: String) {
    ...
}


personTypeOne {
    withName {
       ...
    }
    withAge {
       ...
    }
    withAddress {
       ...
    } 
}

我希望 DSL 能够有效地产生如下所示的调用:personFactory.getPresonTypeOne(name, age, address)

我环顾四周,但我只找到了我可以通过直接调用 PersonTypeOne 构造函数来做到这一点的例子。

我不确定,你的缩进是多少。如果只想隐藏工厂调用,则不需要 DSL。具有命名参数的函数将完成这项工作:

fun personTypeOne(name: String, age: Int, address: String): PersonTypeOne =
    PersonFactory.getPersonTypeOne(name, age, address)

val person1 = personTypeOne(name = "Name", address = "address", age = 42)

如果您确实需要 DSL,则需要定义一个构建器助手 class,其中包含每个属性的方法和一个使用此构建器的函数:

class PersonTypOneBuilder {
    private var name: String? = null
    private var age: Int? = null
    private var address: String? = null

    fun withName(name: () -> String) {
        this.name = name()
    }

    fun withAge(age: () -> Int) {
        this.age = age()
    }

    fun withAddress(address: () -> String) {
        this.address = address()
    }

    fun build() =
        PersonFactory.getPersonTypeOne(
            name ?: throw IllegalStateException(),
            age ?: throw IllegalStateException(),
            address ?: throw IllegalStateException()
        )
}

fun personTypeOne(block: PersonTypOneBuilder.() -> Unit): PersonTypeOne =
    PersonTypOneBuilder().apply(block).build()

现在您可以使用 DSL 了:

val person2 = personTypeOne {
    withName {
        "Bla"
    }
    withAddress {
        "address"
    }
    withAge {
        42
    }
}