Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我应该为具有大量必需属性的类创建生成器吗_Java_Design Patterns_Builder - Fatal编程技术网

Java 我应该为具有大量必需属性的类创建生成器吗

Java 我应该为具有大量必需属性的类创建生成器吗,java,design-patterns,builder,Java,Design Patterns,Builder,如果我有一个拥有相当多属性的类,比如说10个属性,所有这些属性都是正确构造实体所必需的[non-null或non-optional],那么实例化这个类的最佳方法是什么 我应该创建一个没有args构造函数的生成器吗 对所有属性进行withers,并在中检查“non-null” 正在构造的实体的私有构造函数 或 我应该有一个包含所有10个参数的公共构造函数并创建 没有建筑商 拥有一个生成器可以让客户端代码看起来更干净,而拥有一个all args公共构造函数则传递了一个信息,即所有参数都是必需的[

如果我有一个拥有相当多属性的类,比如说10个属性,所有这些属性都是正确构造实体所必需的[non-null或non-optional],那么实例化这个类的最佳方法是什么

  • 我应该创建一个没有args构造函数的生成器吗 对所有属性进行withers,并在中检查“non-null” 正在构造的实体的私有构造函数

  • 我应该有一个包含所有10个参数的公共构造函数并创建 没有建筑商

拥有一个生成器可以让客户端代码看起来更干净,而拥有一个all args公共构造函数则传递了一个信息,即所有参数都是必需的[比如,我用
@javax.annotations.Nonnull
annotation注释所有参数]

我该怎么决定

比如说,

/**
  * 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);
       }
   }
}

构造函数听起来是更好的选择,因为它将强制您提供所有必需的参数,并且您可以在这些参数中运行非空检查。拥有一个包含大量参数的构造函数通常是设计糟糕的标志。也许你会想一个更好的方法来组织你的班级。考虑将一些参数分组为新类(如果它们具有逻辑连接)。这样,您可以创建几个较小的对象,然后将它们作为参数传递给构造函数。您可以修改getter/setter以从这些对象中获得所需的内容。

看起来您的蓝图是重构的有力候选对象;rest确保,如果由于某种原因,您有那么多的成员,那么类的建模(大多数情况下)是错误的

撇开这些不谈,我不确定如何使用构建器,因为必须强制所有成员都必须存在并且具有一定的值,因此更有可能将它们都放在构建器的构造函数中,因为所有成员都是必需的。尽管如此,在这种情况下,IMHO的10个成员的构造函数更有意义


在我看来,一个建设者给了你“语法上的甜头”,没有其他东西……但在你的情况下肯定没有。

当然,建设者是正确的选择。如果您在编写Java时书架上有一本书,它应该是Josh Bloch的。在第二版中,他有一个静态构建器模式

这里没有提到这样做的另外两个原因:

  • 这些参数在生成器中是描述性的,而不仅仅是传递一个int,您有一个名为“weight”或“height”(随便什么)的生成器方法
  • 关键是它鼓励了不变性

认为它只不过是语法上的甜点的想法是荒谬的。如果所有10个参数都有setter,你不是在做OO:任何人都可以在实例生命周期的任何时候随意更改实例的任何内容。

我理解,拥有大量属性的实体有时可能意味着设计不正确,但假设世界上所有实体都可以由少量属性定义,这听起来并不实际。您将创建多少个小班?小实体的深层层次结构不是不可维护的吗?我可以同意你的观点,但这并不意味着他/她不应该考虑在可能的情况下对一些参数进行分组。显然,这在所有情况下都不起作用。如果我让我的构建器有一个无参数的构造函数呢?我将在构建器的构造函数或实体类本身上添加一个很好的文档注释?我将把检查放在主实体的私有构造函数中!在可读性和快速失败之间,这不是一个很好的折衷方案吗?您的成员的默认值是多少?你不是说他们都有价值吗?您可以这样做,但是(对于您的情况)只有在实例化对象时默认分配“某物”,并且没有提供值时才有意义(更可能是
null
)添加了一个简单的代码来解释如何编写生成器和实体。并且,为了便于讨论,让我们假设没有办法进一步重构此实体!:D@DhrumilUpadhyaya是的……那可能是一种方式。事实上,我鼓励你这么做……这是有效的,因为你希望
A
必须遵守这些规则。另外,
this.a1=premissions.checkNotNull(builder.a1)
更简单,因为(丑陋的)静态方法调用将返回
builder.a1
的引用,如果它不是
null
我并不是说我将在实体中使用setter。它们将在静态生成器中。。让我稍微修改一下这个问题是的,这正是你应该做的。所以你的问题是为什么要这么做,而不是一个巨大的构造函数?我想这就是我试图回答的。你可能应该分解更多。您不应该传入10个参数,而应该将其中的一些参数组合到一个对象中,然后作为参数传入该对象。您可能可以将10个参数减少到3个,这样就可以轻松地使用构造函数。