在Effective Java(第2版)的第2项中,作者提到了以下关于在使用Builders时对参数施加不变量的问题:
在将参数从构建器复制到对象后检查它们并在对象字段而不是构建器字段(项目39)上检查它们是至关重要的。如果违反了任何不变量,则构建方法应抛出IllegalStateException(Item 60)。
这是否意味着在构建方法创建目标对象后,应将其传递给验证例程以进行任何所需的验证?
另外,有人可以解释一下这背后的原因吗?
答案 0 :(得分:8)
对象验证是使用构建器创建对象的不可或缺的一部分。虽然您可以使用单独的例程进行验证,但不需要进行此类分离:验证代码可以是执行构建的函数的一部分。换句话说,你可以这样做
TargetObject build() {
TargetObject res = new TargetObject();
res.setProperty1();
res.setProperty2();
validate(res); // This call may throw an exception
return res;
}
void validate(TargetObject obj) {
if (...) {
throw new IllegalStateException();
}
}
或者这个:
TargetObject build() {
TargetObject res = new TargetObject();
res.setProperty1();
res.setProperty2();
if (...) {
throw new IllegalStateException();
}
return res;
}
重要的是验证是在构建目标对象之后而不是之前进行的。换句话说,您需要验证对象的状态,而不是构建器的状态。
答案 1 :(得分:3)
构建器的var totalSpace = (parseInt(headerHeight) + parseInt(containerPT));
console.log(totalSpace + "px");
方法通常会调用它所构建的类的私有构造函数。这就是为什么构建器通常被实现为静态嵌套类的原因,因此它们可以访问私有构造函数。构造函数是验证发生的地方。即使您不使用构建器模式,构造函数也有责任确保对象在创建时处于有效状态。构造函数应创建防御性副本(EJ项39)并验证新对象的字段,不构建器的字段,因为构建器可能在字段存在时发生变异复制。