想必大家對建造者模式也有一定了解,我們今天不走尋常路,使用 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
,也就是預設實現了 getters
和 setters
方法。
然後就是 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 實現建造者模式是不是減少了大量實現程式碼呢。