Написание правильного DSL - PullRequest
0 голосов
/ 01 февраля 2019

Я хочу иметь возможность написать, что вызывает фабричный метод для создания экземпляра объекта вместо прямого вызова конструктора.

У меня есть фабрика с именем PersonFactory, которая реализует метод с именем getPresonTypeOne(name: String, age:Int, address: String).PersonTypeOne имеет три переменные-члены с именами name, age и address.Я хочу иметь возможность написать что-то, что вызывает getPresonTypeOne для создания экземпляра PersonTypeOne вместо прямого вызова конструктора PersonTypeOne.

В идеале, что-то похожее на это

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


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

Я бы хотел, чтобы этот DSL эффективно получал результат вызова, который выглядит следующим образом: personFactory.getPresonTypeOne(name, age, address)

IЯ немного осмотрелся, но я нашел только примеры того, как я мог сделать это, напрямую вызвав конструктор PersonTypeOne.

1 Ответ

0 голосов
/ 01 февраля 2019

Я не уверен, каков твой отступ.Если вы хотите скрыть только заводской вызов, вам не нужен 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
    }
}
...