为什么构建者模式的实现不应该是不可变的?

huangapple go评论54阅读模式
英文:

Why shouldn't builder pattern implementations be immutable?

问题

考虑以下 Kotlin 字符串构建器的实现:

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

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

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

StringBuilder 的内部实现需要一个可变的项目列表,但如果你想要严格遵循不可变性,你可以很容易地重构它成为完全不可变的;例如:

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

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

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

根据 维基百科,列在缺点下面

> 构建器类必须是可变的。

很明显这并非一定如此;正如所展示的,构建器可以被设计成完全不可变的,并且将这种说法列在“缺点”下面似乎表明构建器是不可变的会有一些优势。

所以,我在想是否有任何特定的原因要求构建器的实现必须是可变的?

我只能想到一个原因 - 不可变构建器会产生更高的垃圾回收开销,因为每次都必须返回构建器的新实例。

英文:

Consider the following Kotlin implementation of a string builder:

class StringBuilder {
    private val items = mutableListOf&lt;String&gt;()

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

    override fun toString(): String {
        return items.joinToString(&quot;&quot;)
    }
}

The internal implementation of the StringBuilder requires a mutable list of items, but if you wanted to take immutability seriously, you could easily refactor this to be completely immutable; for example:

class StringBuilder(private val items: List&lt;String&gt; = emptyList()) {

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

    override fun toString(): String {
        return items.joinToString(&quot;&quot;)
    }
}

According to Wikipedia, listed under Disadvantages

> Builder classes must be mutable.

This clearly isn't the case; as demonstrated, a builder can be designed to be completely immutable, and the fact that this statement is listed under "Disadvantages" would suggest that it would be advantageous for builders to be immutable.

So, I was wondering if there are any specific reasons why builder implementations should be mutable?

I could only think of one reason - the garbage collection overhead for an immutable builder will be higher as new instances of the builder have to be returned each time.

答案1

得分: 2

  • 建造者模式的缺点包括:(3)
  • ...
  • 建造者类必须是可变的。
  • ...

对于维基百科上的引用演示文稿,没有提到“建造者类必须是可变”或将其列为缺点。因此,我认为该引用的位置是具有误导性的。

我认为您提到的垃圾回收开销是像Kotlin这样的语言中唯一的缺点?(除了确保在复杂的建造者中深度复制字段的不便之外)

英文:

> Disadvantages of the Builder pattern include: (3)
> - ...
> - Builder classes must be mutable.
> - ...

The referenced presentation in that Wiki for that bullet point does not say "builder classes must be mutable" or list it as a disadvantage. So I find the placement of that reference to be misleading.

I think your point about garbage collection overhead is the only disadvantage in languages like Kotlin? (Aside from the inconvenience of ensuring you deep copy your fields in complex builders)

答案2

得分: 1

你的不可变示例是在纯函数式语言中实现生成器的方式。正如你所说,问题在于所有额外的分配和相关的 CPU 循环。

英文:

Your immutable example is the way a builder would be implemented in a pure functional language. As you said though, the issue is all the extra allocations and associated CPU cycles.

huangapple
  • 本文由 发表于 2023年2月16日 02:53:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75464276.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定