编写适当的DSL

时间:2019-02-01 04:06:55

标签: design-patterns kotlin factory dsl gradle-kotlin-dsl

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

我有一个名为PersonFactory的工厂,该工厂实现了称为getPresonTypeOne(name: String, age:Int, address: String)的方法。 PersonTypeOne具有三个成员变量,分别名为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构造函数来做到这一点。

1 个答案:

答案 0 :(得分:1)

我不确定,您的缩进是什么。如果您只想隐藏工厂电话,则不需要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 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
    }
}