“ StringBuilder”是Builder设计模式的应用程序吗?


31

是“构建器”模式仅限于解决“ telescoping构造函数”反模式,还是可以说也解决了复杂的不可变对象创建这一更普遍的问题?

StringBuilder班在其名称中的“建设者”,但它没有任何可伸缩的构造函数,它只是帮助我们收集了所有我们需要传递给一个不可变对象的构造函数的数据。

在我看来,答案似乎是非常明确的“是”,但是在该主题上似乎存在一些分歧,因此我希望有人可以对此进行澄清。

我在回答这个问题:程序员SE:在构造函数中合法的“实际工作”?OP想要创建一个包含复杂树的(可能是不可变的)对象,然后弹出“ builder”模式的想法,在研究它时,我发现了这个问答,似乎是在说“ StringBuilder”风格的对象创建是不是 “建设者”模式的应用,这是我不明白原因:#1 - StringBuilder的和Builder模式。(据我所知,回答该问题的人未能提出令人信服的观点。)


2
我发现Paul Sasik对Stack Overflow问题的回答完全令人信服:StringBuilder是解决串联不可变字符串的性能问题的“替代方法”,仅此而已。充其量,StringBuilder是“不幸的命名”。我想您可以说StringBuilder可以“构建”网页,但这是通用机制特定应用
罗伯特·哈维

3
Paul Sasik的答案对于Java是错误的-我查看了底层的源代码。StringBuilder似乎使用底层字符数组来表示String,并允许您随时执行诸如插入和删除之类的操作。最终,我认为StringBuilder是不可变String对象的一种解决方法,但在我看来,它满足了Builder模式的意图。
Thomas Owens

4
我确实需要多考虑一下-这让我感到困扰。我几乎开始写出为什么诸如StringBuilder之类的东西是Builder模式的版本,而其他所有人都错了。但是我发现了一些缺点,说服自己说错了,但后来设法回到了我的第一个想法。如果仅查看Builder模式的意图,很容易看到“ StringBuilder是一个Builder”。如果您查看Builder模式的结构,则难度会更大。
Thomas Owens

1
对于它的价值,关于Stack Overflow的答案与我最初的想法一致,即StringBuilder是构建器实现,并且注释很有趣。因此,您可以找到参数的两面。我赞成这个问题-我不知道我能否建立一个好的答案,但是这肯定是一个有趣的问题。我会考虑的。
Thomas Owens

2
并非所有的GoF模式都能经受住时间的考验。我不是在,我只是在说。
2015年

Answers:


36

A StringBuilder与构建器模式相似,但是与该设计模式的GoF描述没有太多共享。设计模式的初衷是

将复杂对象的构造与其表示分开,以便同一构造过程可以创建不同的表示。

—来自Design Patterns,由Gamma,Helm,Johnson和Vlissides撰写。

(注意:“复杂”主要是指“由多个部分组成”,不一定是“复杂”或“困难”)

这里的“不同表示”是关键。例如,假设此构建过程:

interface ArticleBuilder {
  void addTitle(String title);
  void addParagraph(String paragraph);
}

void createArticle(ArticeBuilder articleBuilder) {
  articleBuilder.addTitle("Is String Builder an application of ...");
  articleBuilder.addParagraph("Is the Builder Pattern restricted...");
  articleBuilder.addParagraph("The StringBuilder class ...");
}

我们可能会根据提供的具体实现而以a HtmlDocument或a TexDocument或a 结尾MarkdownDocument

class HtmlDocumentBuilder implements ArticleBuilder {
  ...
  HtmlDocument getResult();
}

HtmlDocumentBuilder b = new HtmlDocumentBuilder();
createArticle(b);
HtmlDocument dom = b.getResult();

因此,Builder模式的中心点是多态。设计模式书将这种模式与抽象工厂进行了比较:

抽象工厂与生成器相似,因为它也可以构造复杂的对象。主要区别在于Builder模式专注于逐步构建复杂的对象。[…] Builder将产品退回作为最后一步,但是就抽象工厂而言,产品将立即退回。

—来自Design Patterns,由Gamma,Helm,Johnson和Vlissides撰写。

这个逐步的方面已经成为Builder模式的更流行的方面,因此通常来说,Builder模式的理解如下:

将对象的构造分为多个步骤。这使我们即使在不支持这些功能的语言中也可以使用命名参数或可选参数。

维基百科定义了这样的模式:

构建器模式是对象创建软件设计模式。与旨在实现多态性的抽象工厂模式和工厂方法模式不同,构建器模式的意图是为可伸缩构造函数反模式[需要引用]找到解决方案。[…]

构建器模式还有另一个好处。它可以用于包含平面数据(html代码,SQL查询,X.509证书...)的对象,也就是说,这些数据不容易编辑。此类数据无法逐步编辑,必须立即进行编辑。构造此类对象的最佳方法是使用构建器类。[需要引用]

—来自Wikipedia上的Builder Pattern,由各种贡献者提供。

因此,如我们所见,对该名称所指的是哪种模式并没有真正的共识,而且在某些方面,不同的定义甚至彼此矛盾(例如,关于多态性对建造者的相关性)。

StringBuilder模式具有各种解释的唯一共同属性是,产品是逐步创建的,而不是一次性创建的。它不能完全理解GoF对设计模式的定义,但请注意,设计模式是可塑的概念,旨在促进交流。我将继续称其StringBuilder为Builder模式的一个示例,尽管它是一个非典型的示例-Java中这种结构的主要原因是在不可变字符串存在的情况下进行了高性能连接,但并不是一些有趣的面向对象设计。


7
在我看来,创建不可变对象似乎是Builders的更常见用法之一-我认为这已经取代了GoF所描述的主要用途,因此同意,最好将其最好地描述为模式实例。
2015年

同意创建不可变图的用法,Builder DSL的另一个用例对于在单元+集成测试期间创建假数据/对象母亲的大图确实有用。
StuartLC '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.