You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何建造者模式的实现不应设计为不可变?

建造者模式:可变实现是否更必要?

先看两个Kotlin实现的StringBuilder:

可变版本

class StringBuilder {
    private val items = mutableListOf<String>()

    fun append(item: String): StringBuilder {
        items.add(item)
        return this
    }

    override fun toString(): String {
        return items.joinToString("")
    }
}

这个版本内部依赖可变列表items累积内容,每次调用append都会修改自身状态并返回当前实例。

不可变版本

class StringBuilder(private val items: List<String> = emptyList()) {

    fun append(item: String): StringBuilder {
        return StringBuilder(items + item)
    }

    override fun toString(): String {
        return items.joinToString("")
    }
}

这个完全不可变的实现,每次调用append都会创建包含新内容的StringBuilder实例,原实例状态始终保持不变。

维基百科中建造者模式词条的“缺点”部分提到:

建造者类必须是可变的。

但显然这个说法并不准确——上面的例子就证明了不可变建造者是可行的。而将“必须可变”列为缺点,也侧面体现了不可变设计的优势。

那有没有特定场景或原因,使得建造者模式应当采用可变设计?

我能想到的最核心原因是性能与GC开销:不可变建造者每次调用方法都会生成新实例,在频繁构建复杂对象的场景下,大量临时对象的创建和销毁会显著增加垃圾回收的压力,拖慢程序运行速度。

除此之外,还有几个场景更适合可变建造者:

  • 状态复用与共享:如果需要在多个逻辑分支中复用建造者的中间状态,可变建造者可以直接修改自身,无需创建多个实例;不可变建造者则需要传递不同的实例,会增加代码复杂度和内存占用。
  • 构建过程的调试与跟踪:可变建造者的状态是连续变化的,调试时可以直观跟踪每一步的修改;不可变建造者每次都是全新实例,跟踪状态变化会更繁琐。
  • 现有生态的兼容性:很多主流类库(比如Java标准库的StringBuilder)的建造者都是可变设计,采用可变实现能更好地兼容现有代码,减少适配成本。

内容的提问来源于stack exchange,提问作者Matthew Layton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:50:46