介绍
主要作用
逐步构造复杂对象,该对象的属性更多的扩展属性,如Glide的使用。
组成

-  
Builder:提供逐步创建产品的步骤
 -  
Director:创建可复用的特定产品(规定Builder规定一系列的步骤创建产品,非必须)
 -  
Product:具体的产品类(可能包含了相同的父类或接口)
 
kt中实现方案
Kt中可以简化该模式的使用,下面介绍常见写法
1. 使用具名可选参数
class Computer(
    val mainboard: String, // 主板
    val cpu: String, // 处理器
    val ram: String, // 内存
    val battery: String, // 电源
    val gpu: String? = null, // 显卡
    val hardDisk: String? = null, // 硬盘
    val networkInterface: String? = null, // 网线接口
    val cdDriver: String? = null, // 光驱
    val os: String? = null, // 系统
    val chassis: String? = null, // 机箱
    val mouse: String? = null, // 鼠标
    val keyboard: String? = null, // 键盘
    val monitor: String? = null // 显示器
)
fun main() {
    // 具名参数
    val computer = Computer(
        "超微X8QB6-F", "Intel Xeon E7-8870", "海盗船(CORSAIR) 复仇者LPX DDR4 2133 64GB 7000", "西门子豪华供电柜",
        gpu = "Leadtek/丽台Quadro Plex 7000",
        os = "Windows 11",
        mouse = "RAPOO雷柏 3710 2.4G激光无线鼠标",
        keyboard = "Optimus Maximus 多功能 概念式键盘",
        monitor = "Sharp/夏普 LB-1085 108英寸 FULL HD专业液晶显示器"
    )
}
 
具名函数的优点:
- 代码简洁优雅,无论是 Product 的类结构,或者是创建一个 Product 实例
 - 创建 Product 实例时,显式指定参数名即可,无须按顺序传入
 - 所有参数均使用 val 声明,相比 Builder 中使用 var 更加安全
 
2. 使用apply,also作用域函数
class Car {
    var color: String = ""
    var doors: Int = 0
    var wheel: String = ""
    override fun toString(): String {
        return "Car(color='$color', doors=$doors, wheel='$wheel')"
    }
}
fun main() {
    val car = Car().apply {
        color = "Red"
        doors = 4
        wheel = "Good"
    }
    println(car)
}
 
3. 标准写法
我们这里使用带接收器的Lambda表达式。
class Car1(
    val model: String? = null,
    val year: Int = 0
) {
    private constructor(builder: Builder) : this(
        builder.model,
        builder.year
    )
    class Builder {
        var model: String? = null
        var year: Int = -1
        fun build() = Car1(this)
    }
    companion object {
        /**
         * 带接收者的函数类型,这意味着我们需要向函数传递一个Builder类型的实例
         */
        inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build()
    }
    override fun toString(): String {
        return "Car1(model=$model, year=$year)"
    }
}
fun main() {
    val car2 = Car1.build {
        model = "名字"
        year = 2017
    }
    println(car2)
}
 
4. 结合lambda DSL优雅写法弹框示例
import androidx.annotation.StringRes
class Dialog1 {
    var title: String = ""
    var content: String = ""
    // 内敛函数结合lambda
    inline fun show(func: Dialog1.() -> Unit) {
        this.func()
        this.show()
    }
    fun show() {
        println("title:$title,content:$content")
    }
}
class Dialog2 {
    var title: String = ""
    var content: String = ""
    fun title(@StringRes res: Int? = null, text: CharSequence? = null): Dialog2 {
        text?.let {
            title = it.toString()
        }
        return this
    }
    fun content(@StringRes res: Int? = null, text: CharSequence? = null): Dialog2 {
        text?.let {
            content = it.toString()
        }
        return this
    }
    inline fun show(func: Dialog2.() -> Unit) {
        this.func()
        this.show()
    }
    fun show() {
        println("title:$title,content:$content")
    }
}
class Dialog private constructor(
    val title: String,
    val text: String?,
    val onAccept: (() -> Unit)?
) {
    class Builder(val title: String) {
        var text: String? = null
        var onAccept: (() -> Unit)? = null
        fun setText(text: String?): Builder {
            this.text = text
            return this
        }
        fun setOnAccept(onAccept: (() -> Unit)?): Builder {
            this.onAccept = onAccept
            return this
        }
        fun build() = Dialog(title, text, onAccept)
    }
}
fun main() {
    Dialog1().show {
        title = "标题"
        content = "内容"
    }
    Dialog2().show {
        title(text = "标题")
        content(text = "内容")
    }
    val dialog1 = Dialog.Builder("Some title")
        .setText("Great dialog")
        .setOnAccept { println("I was clicked") }
        .build()
    val dialog2 = Dialog.Builder("Another dialog")
        .setText("I have no buttons")
        .build()
    val dialog3 = Dialog.Builder("Dialog with just a title").build()
}
 
总结
应用场景
盖房子,定制汽车
优点
- 分步创建更加灵活
 - 可以复用相同的制作代码
 - 严格遵循单一职责原则
 
缺点
 代码整体复杂度增加
生成器模式就是为了构建复杂对象,创建对象的方式是多步骤的。关于建造模式的变种写法参考(Java 大白话讲解设计模式之 – 建造者(Builder)模式 - 简书)
参考:
Kotlin 自带的Builder建造者模式
Kotlin设计模式-Builder模式 - 简书
秒懂设计模式之建造者模式(Builder pattern)
给人看的Kotlin设计模式——构造者模式
Kotlin - 改良构建者模式 - 掘金
你会用Kotlin实现构建者模式吗?
Kotlin - 改良构建者模式 - 掘金



















