Kotlin 中使用 DSL 實現建造者模式

居合子發表於2017-05-18

想必大家對建造者模式也有一定了解,我們今天不走尋常路,使用 DSL 的方法優雅地實現建造者模式。

先上程式碼

data class User(var id: String = "",
                var username: String = "default",
                var password: String = "000000")


fun buildUser(buildAction: User.() -> Unit) = User().apply(buildAction)

fun modifyUser(user: User, modifyAction: User.() -> Unit) = user.apply(modifyAction)

fun main(args: Array<String>) {
    var user = buildUser {
        id = UUID.randomUUID().toString()
        username = "Juhezi"
        password = "123456"
    }
    println(user)
    user = modifyUser(user) {
        id = "0"
        username = "Kotlin"
        password = "654321"
    }
    println(user)
}複製程式碼

執行結果

User(id=d762b3d7-fe69-4735-bed4-a99b2e88bd82, username=Juhezi, password=123456)
User(id=0, username=Kotlin, password=654321)複製程式碼

分析一波

程式碼和效果都看過了,接下來我們細細分析一下這段程式碼。

首先,第一行定義了一個 data class,在 Kotlin 中 data class 的作用是: Create a POJO with getters, setters, equals(), hashCode(), toString() and copy() in a single line,也就是預設實現了 getterssetters 方法。

然後就是 fun buildUser(buildAction: User.() -> Unit) = User().apply(buildAction) 這個 build 方法,這個方法需要一個 User.() -> Unit 型別的引數,這個類似你可能不明白是什麼,其實,它指得是一個函式型別,即 User 的一個方法,這個方法會返回 Unit。

而 User().apply(buildAction) 的作用就是,首先建立一個 User() 物件,然後執行傳入的 buildAction 方法,然後返回這個 User() 物件。

var user = buildUser {
    id = UUID.randomUUID().toString()
    username = "Juhezi"
    password = "123456"
}複製程式碼

可以看到,我們在大括號裡直接就可以修改 User 的 id,這裡其實是呼叫了 id 的 setter,前面說過了,data class 會自動實現 getters 和 setter 方法。同時那個大括號可以看作是剛剛建立的 User 的方法體,在自己的內部,當然可以直接使用自己的方法咯。

下面的 modifyUser也是一樣的。

比較一下,使用 DSL 實現建造者模式是不是減少了大量實現程式碼呢。

相關文章