什么是修订后的构建模式?
GoF的原始Builder模式与Joshua Bloch的“修订的GoF Builder模式”有什么区别?
GoF模式侧重于抽象构造步骤,以便通过改变构建器可以获得不同的结果,而“修订构建器”针对多个构造函数添加的不必要复杂性的问题。 所以GoF模式更多的是关于抽象,修改后的模式更多的是简单性(IMO)。
请查看http://en.wikipedia.org/wiki/Builder_pattern和http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html中的示例,它应该非常清楚。
请注意Mikko的答案 : Hansen的例子有一些问题 – 或者至少与Bloch的版本存在差异,尽管我认为Bloch的版本更优越。
特别:
首先, Widget
的字段在Builder.build()
而不是在Widget
构造函数中设置,因此不是(也不可能是) final
。 Widget
被认为是不可改变的,但没有什么可以阻止另一个程序员出现并稍后添加setter。
其次,Hansen的构建方法中的评论说“预创建validation就在这里”。 布洛赫(EJ 2ed.p.15)说:
在将参数从构建器复制到对象之后检查[不变量]并在对象字段而不是构建器字段(项目39)上检查它们是至关重要的。
如果你翻到第39项(第185页),你会看到推理:
[This]保护类免于在检查参数的时间和复制时间之间的“漏洞窗口”期间从另一个线程更改参数。
Widget
中的字段是不可变的,不需要任何防御性复制,但是只要坚持正确的模式就更安全了,以防有人出现并稍后添加Date
或数组或一些可变的Collection
。 (它还可以防止在调用build()
的过程中修改Builder
另一个线程,但这是一个非常狭窄的安全窗口,所以最好只确保在线程之间不共享Builder
。)
更像Blochlike的版本是:
public class Widget { public static class Builder { private String name; private String model; private String serialNumber; private double price; private String manufacturer; public Builder( String name, double price ) { this.name = name; this.price = price; } public Widget build() { Widget result = new Widget(this); // *Post*-creation validation here return result; } public Builder manufacturer( String value ) { this.manufacturer = value; return this; } public Builder serialNumber( String value ) { this.serialNumber = value; return this; } public Builder model( String value ) { this.model = value; return this; } } private final String name; private final String model; private final String serialNumber; private final double price; private final String manufacturer; /** * Creates an immutable widget instance. */ private Widget( Builder b ) { this.name = b.name; this.price = b.price; this.model = b.model; this.serialNumber = b.serialNumber; this.manufacturer = b.manufacturer; } // ... etc. ... }
所有Widget
字段现在都是final
字段,并且所有字段都在构建后进行validation。