更简洁的Builder模式?

Dmy*_*tro 5 java builder

当我在Josh的Bloch书中审查Builder模式时,我提出了更简单的实现,但我不确定它是否合适.例如:

public class Test {
    public static void main(String[] args) {
        Numbers first = new Numbers.Builder().setD(3.14).build();
        System.out.println(first);
        Numbers second = new Numbers.Builder().setI(17).setF(1.24F).build();
        System.out.println(second);
        System.out.println(first);
    }
}

final class Numbers {
    private int i;
    private long l;
    private float f;
    private double d;

    private Numbers() {}


    public static class Builder {
        private final Numbers instance = new Numbers();

        public Builder setI(int i) {
            instance.i = i;
            return this;
        }

        public Builder setL(long l) {
            instance.l = l;
            return this;
        }

        public Builder setF(float f) {
            instance.f = f;
            return this;
        }

        public Builder setD(double d) {
            instance.d = d;
            return this;
        }

        public Numbers build() {
            return instance;
        }
    }

    @Override
    public String toString() {
        return String.format("%4d %4d %7.3f %7.3f", i, l, f, d);
    }
}
Run Code Online (Sandbox Code Playgroud)

它仍然可以被视为一个Builder模式或我错过了什么?

编辑

那这个呢?

//...

private Numbers() {}


private Numbers(Numbers o) {
        i = o.i;
        l = o.l;
        f = o.f;
        d = o.d;
    }

public static class Builder {
        private final Numbers instance = new Numbers();

          //...

        public Numbers build() {
            return new Numbers(instance);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 4

您的代码的问题在于,如果您build对同一个Builder实例调用两次,您将获得相同的Numbers实例。Builder如果您在调用build并获取实例后调用方法Numbers,您将更改该实例。构建器创建的实例一旦构建就应该独立于构建器。

  • 与此相关的其他问题是,这意味着您的任何字段都不能是“final”,并且您的构造函数无法对字段执行任何验证(也许您想要一些依赖于多个字段的逻辑,例如“if i == 3那么 f 不能为负数”)。 (4认同)