如Effective Java中所述,嵌套的Builder类是否真的有必要?

Joe*_*Min 5 java design-patterns builder

因此,在着名的Effective Java书中,它引入了一个Builder模式,您可以在其中使用内部静态Builder类来实例化一个类.这本书建议了以下类的设计:

public class Example {
    private int a;
    private int b;

    public static class Builder() {
        private int a;
        private int b;

        public Builder a(int a) {
            this.a = a;
            return this;
        }

        public Builder b(int b) {
            this.b = b;
            return this;
        }

        public Example build() {
            return new Example(this);    
        }
    }

    private Example(Builder builder) {
        this.a = builder.a;
        this.b = builder.b;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我无法理解为什么我们真的需要内心Builder class上面的代码有字段声明的重复行(int a,b),如果我们有更多字段,这将变得相对混乱.

为什么不脱掉Builder类,让Example类接受类中的所有set方法Builder

所以要实例化Example,它将成为Example e = new Example().a(3).b.(3);而不是Example e = new Example.Builder.a(3).b(3).build();


注意:本书为具有很长参数列表的类建议了这种模式.

And*_*ner 10

Builder是构建复杂对象的模式.我不认为你的榜样很复杂; 实际上,构建器添加了大量不必要的代码,而不仅仅是使用构造函数参数.

您想要使用构建器的原因有几个:

  • 构造复杂的不可变对象.不可变对象需要具有最终(或逻辑上最终)字段,因此必须在构造时设置它们.

    假设您有N个字段,但您只想在某些用例中明确设置其中的一些字段.您需要最多2 ^ N个构造函数来覆盖所有情况 - 称为"telescoping",因为参数列表的长度变得越来越长.构建器允许您为可选参数建模:如果您不想设置该参数,请不要调用该setter方法.

  • 允许自我记录参数的含义.通过适当地命名setter方法,您可以一目了然地看到值的含义.

    它还有助于验证您是否意外地反转了相同类型的参数,因为您可以看到每个值的用途.