PHpullh
학습 라이브러리/Kotlin/Builder 패턴 & DSL

KOTLIN · 디자인패턴

Builder 패턴 & DSL

Kotlin의 람다 수신자(lambda with receiver)로 읽기 쉬운 DSL을 만듭니다.

디자인패턴중급DSLbuilderlambda-receiver@DslMarker

핵심 설명

Kotlin의 람다 수신자(lambda with receiver)로 읽기 쉬운 DSL을 만듭니다.

Kotlin code

// HTML DSL 스타일 빌더
data class HtmlTag(val name: String) {
    val children = mutableListOf<String>()
    var text: String = ""

    fun render(indent: Int = 0): String {
        val pad = "  ".repeat(indent)
        return "$pad<$name>$text</$name>"
    }
}

class HtmlBuilder {
    private val tags = mutableListOf<HtmlTag>()

    fun div(init: HtmlTag.() -> Unit) {
        tags.add(HtmlTag("div").also(init))
    }
    fun p(text: String) {
        tags.add(HtmlTag("p").also { it.text = text })
    }

    fun build() = tags.joinToString("
") { it.render() }
}

fun html(init: HtmlBuilder.() -> Unit) =
    HtmlBuilder().also(init).build()

// 설정 DSL 패턴
data class ServerConfig(
    val host: String = "localhost",
    val port: Int = 8080,
    val timeout: Int = 30
)

fun server(block: ServerConfig.() -> ServerConfig) =
    ServerConfig().block()

fun main() {
    val page = html {
        div { text = "헤더" }
        p("본문 내용")
        p("두 번째 단락")
    }
    println(page)
}

학습 팁

Kotlin 표준 라이브러리의 buildList { }, buildMap { }, buildString { }도 동일한 DSL 패턴입니다.

주의할 점

DSL 블록 안에서 외부 DSL 메서드가 우연히 호출되면 혼란스럽습니다. @DslMarker 어노테이션으로 스코프를 제한하세요.

자주 묻는 질문

Builder 패턴 & DSL란 무엇인가요?

Kotlin의 람다 수신자(lambda with receiver)로 읽기 쉬운 DSL을 만듭니다.

Builder 패턴 & DSL 학습 시 주의할 점은 무엇인가요?

DSL 블록 안에서 외부 DSL 메서드가 우연히 호출되면 혼란스럽습니다. @DslMarker 어노테이션으로 스코프를 제한하세요.