建造者设计模式的缺点

17

使用构造器设计模式会有什么缺点吗?会吗?

编辑 - 我想知道使用构造器设计模式是否会有任何负面影响?在GOF的书中,他们提到了设计模式的好处和坏处。但他们没有提到构造器设计模式的任何不良后果。


6
没有上下文无法回答这个问题。您想用生成器模式解决什么问题?生成器模式是解决某些静态类型语言问题的一种方式,但不能用来解决同一语言中的其他问题,因此无法确定它是否“好”或“坏”。 - Yann Ramin
1
这要看情况。如果你的类似乎会有超过一小撮参数的构造函数,那么建造者设计模式将是一个不错的选择。然而,如果你所设计的类唯一的目的是在屏幕上打印字符串“裤子”,那么这可能就有点杀鸡焉用牛刀了... - Robben_Ford_Fan_boy
5个回答

16

使用构建器模式相对于例如构造函数参数和/或设置器/获取器,确实会在DTO中创建更多的代码(并可能引入更多的复杂性)。

在我看来,这不是一个大问题,在大多数情况下没有太多额外的代码。如果您有一个对象具有一些必填和一些可选参数,则使用构建器模式将是物超所值的。


虽然这是一个旧的话题,但我认为没有理由将“必须”或“可选”作为参数来决定你应该使用哪种方法来获取数据集。回想当人们编写普通的 C / C++ 代码时,我们并没有这么多复杂的东西。我认为我们知道自己在做什么。当然,事物会不断进步,但对我来说,建造者模式会让你的类变得混乱,增加更多的工作量,使代码更难读,并且会增加维护成本。我见过它的实现,首先有一个Builder,然后是构造函数和设置器。三个都要用到。而这一切都是因为有人写了一本叫做Effective Java的书。 - Lawrence
强制和可选项是在《Effective Java》中展示的构建器模式的一个特性,因此这是需要考虑的。当然,如果您需要不可变性。有人曾经滥用过它的论点真的很糟糕。如果您愿意,可以使用公共字段,这样代码量会少得多。 - Jarle Hansen

11

当模式被滥用/误用时,该模式才具有不利因素。即该模式根本没有解决/适用于实际的技术/功能问题。这时你应该寻找另一个模式来解决特定的问题。

这并不专门适用于建造者模式,而是适用于设计模式的普遍情况。


更新:如果您有兴趣学习各种设计模式(特别是GoF设计模式书中提到的模式)和Java API中的实际示例,则可以查看此答案:Java核心库中GoF设计模式的示例 会很有帮助。它包含了链接到维基百科文章以详细解释这些模式。


4

我支持Jarle的帖子

但是,当涉及到缺点时:

  • 如果您需要将DTO与Hibernate或JAXB进行映射,则构建器模式不适合。
  • 如果您出于某些原因想要可变对象。
  • 对于只有两个或三个字段的小型DTO,它只是额外负担,您应该使用一个或两个构造函数。除非您知道/相信DTO将来会包含更多字段。

-1,所有三点都是错误的。建造者模式与数据库映射、可变性或不可变性完全无关,你所提到的第三点表明你实际上并不知道建造者模式的目的是什么。 - Angel O'Sphere
1
@Angel:映射框架通常使用set方法和构造函数来设置对象的不同值。你用过泛型映射框架吗?你最后两个论点相当薄弱。 - Espen
“setMethods”或“constructors”在映射框架中的使用与建造者模式有什么关系?正确答案是:_没有_。我强烈建议阅读GOF对建造者模式的定义。 - Angel O'Sphere
2
+1 给 @AngelO'Sphere 的 -1 补回来。Espen 所说的 Builder 模式是 Josh Bloch 在 Effective Java 2nd Ed. 中提到的(参见 这个答案)。在该模式中,Builder 使用的构造函数是私有的;该模式的一个目标是通过允许所有字段为 final(而不是通过 setter 进行初始化)来鼓励不可变性;对于具有少量异构字段的对象,它确实过度了。(尽管考虑使用静态工厂方法和私有构造函数仍然值得,这将方便以后添加 Builder。) - David Moles
1
只有一点注释,你不知道未来的情况,因此你不应该基于假设编写代码(除非下一个迭代明确说明不同)。编写代码时,应该按照规格书最终版的要求进行。 (再次强调,除非你知道下一个迭代明确表示不同)。这样最终效率将尽可能高。 - Lawrence
显示剩余3条评论

4

建造者模式,当与在Java中克服可选参数不足的想法一起使用时,您将失去编译器提供的静态分析(以及IDE提供的所有良好重构功能)。这意味着您只能在运行时检测到某些必需的参数缺失,而不能立即让IDE告诉您出了什么问题...


2
与望远镜构造者相比,
  • 静态分析的损失
  • 对于丢失的必需参数,需要抛出异常并在某处捕获
  • 如果您在构建器中使用装箱类型来表示尚未设置的原始值,则会出现大量自动装箱/拆箱-这样可以允许难以发现的NullPointerExceptions。望远镜构造函数中没有此类问题-您只需传递原始值。
  • 更多的代码

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接