如果我有一个具有相当多属性的类,比如10,所有这些都需要[非null或非可选]来正确构造实体,那么实例化这个类的最佳方法是什么?
- 我是否应该创建一个没有args构造函数的构建器,该构造函数具有所有属性的符号,并在正在构造的实体的私有构造函数中检查“非null”
OR
- 我应该有一个包含所有10个参数的公共构造函数并创建NO Builder吗?
拥有一个构建器使得客户端代码看起来更干净,而拥有一个所有args公共构造函数传达了所有参数都需要的消息[比如,我用 @javax.annotations.Nonnull
注释注释所有参数]
我该怎么决定?
例如,
/**
* PLEASE SET SOME VALUE FOR ALL THE ATTRIBUTES!
*/
Class A {
private final String a1;
...
private final TypeN an;
private A(Builder builder) {
// copy all all the parameters
this.a1 = builder.a1;
...
this.an = builder.an;
// null checks
Preconditions.checkNotNull(this.a1);
...
Preconditions.checkNotNull(this.an);
}
public static class Builder{
private String a1;
...
private TypeN an;
public Builder withA1(String a1) {
this.a1 = a1;
return this;
}
// other withers
public A build() {
return new A(this);
}
}
}
3 回答
当然,Builder是正确的选择 . 如果你在编写Java时书架上有一本书,它应该是Josh Bloch的Effective Java . 在第2版中,他有一个静态构建器模式 .
这里没有提到另外两个原因:
参数在构建器中是描述性的,而不是仅传递int,您有一个名为'weight'或'height'(无论如何)的构建器方法
重点是它鼓励不变性
它只不过是语法糖的想法是荒谬的 . 如果你在所有10个参数上都有一个setter,你就不会做OO:任何人都可以在生命周期的任何一点随意更改任何关于实例的内容 .
构造函数听起来更好,因为它会强制您提供所有必需的参数,并且您可以在其中运行非null检查 . 拥有带有大量参数的构造函数通常是糟糕设计的标志 . 也许你会想到一个更好的方法来构建你的课程 . 考虑将一些参数分组为新类(如果它们具有逻辑连接) . 有了这个,您可以创建一些较小的对象,然后将它们作为参数传递给构造函数 . 您可以修改getters / setter以获取这些对象所需的内容 .
看起来你的蓝图是一个很有可能被重构的候选人;请确保,如果由于某种原因,你有那么多成员,那么这个类就会被错误地建模(大部分时间) .
离开那个旁边,我不确定如何使用构建器,因为你必须强制所有成员必须存在并具有一些 Value ,所以它是's more likely that you put them all also in the builder'的构造函数本身,因为所有成员都是必需的 . 据说,在这种情况下,恕我直言,10个成员的构造函数更有意义 .
在我看来,一个建筑师给你“语法糖”,没有其他......但绝对不是你的情况 .