java嵌套构建器模式重复字段

时间:2017-08-06 21:11:34

标签: java

我在网上遇到的嵌套构建器模式通常都是这样的:

Person

我的问题是,是否有必要复制Builderclass Person{ private int id; private String name; private int age; ... so on private Person(){} public static class Builder{ private Person person = new Person(); public Builder id(int id){ this.person.id = id; return this; } public Builder name(String name){ this.person.name = name; return this; } .... so on public Person build(){ return person; } // UPDATED -- another build method public Person build(){ Person built = this.person; this.person = new Person(); return built; } } } 中的字段?这似乎是很多冗余的代码。我的第二个问题是,以下代码是否可以替代,为什么或为什么不呢?

ultimate truth

注意:我理解这个主题可能是固执己见的,可能没有“正确”的答案,但我只想听到不同的想法和意见。我不是在寻找{{1}}。

1 个答案:

答案 0 :(得分:2)

只要符合以下条件,您的代码就可以了:

  1. 您将Person成员变量保密(您正在这样做)
  2. 您没有提供允许修改这些成员变量的方法(您显示的代码没有,但您已经省略了部分变量)
  3. 这些成员变量是不可变的,或者您确保getter提供它们的副本。通常更好的是成员已经是不可变的(提示:甚至是java集合)。否则你将在每个getX调用上创建实例。
  4. 一旦调用了Builder.build,没有人必须能够修改Person实例状态,甚至不能修改Builder本身。 您发布的代码中没有发生这种情况
  5. 构建器不会公开"时间实例"正在建造(如果有的话)。除了构建方法的返回之外,不得暴露任何实例。
  6. 有关于哪种是首选方式的意见,大多数时候都是品味问题。但就正确与否而言,通过一些修改,这种方法会很好。最后,在调用构建之前发生的事情纯粹是内部构建器。这是一个实施问题。重要的是要满足以前的规则。

    要修复规则4:您的Builder.build方法应该返回正在使用的临时实例的深层克隆(有一些方法可以解决这个问题,而无需指定每个字段)。或者,您应该在构建器中有一个标志,一旦调用构建,就禁止在Builder实例上调用任何其他方法。

    旁注:我通常更喜欢Builder类也使用私有构造函数。我会在Person类上有这个:

    public static Builder builder() {
        return new Builder();
    }
    

    这可以让您在初始化Builder的过程中获得更大的灵活性,甚至可以让几个构建器方法在"预配置"方面完全不同。构建器(因为它们是方法,所以命名比构造函数更灵活:))