在扩展类上使用Builder构造函数?

时间:2014-06-02 18:22:33

标签: java generics constructor effective-java javabuilders

我正在实现一个Builder构造函数,如Joshua Bloch的“Effective Java 2nd Edition”中所述。但是,当我尝试扩展类及其构建器时,我遇到了一些复杂问题。本质上,扩展的构建器在扩展中child类设置了返回父Builder类型的字段方法,而不是子构建器类型。

当然,我可以在属性构建链中回转到ChildBuilder(如我的main方法所示),但它不是无缝的,这会破坏Builder的目的,它也迫使我分离父设置器和儿童二传手。

我尝试使用泛型,但最终变得比演员更加冗长。

有没有办法可以一致地让构建器上的set方法返回实际实例化的构建器类型?

public class ParentObj {

    public static void main(String[] args) { 

    ChildObj childObj = ((ChildObj.ChildBuilder) (new ChildObj.ChildBuilder())
                .prop1(11)
                .prop2(21)
                .prop3(14))
                .prop4(12)
                .prop5(33)
                .build();
    }



    private int prop1;
    private int prop2;
    private int prop3;

    protected ParentObj(Builder builder) {
        this.prop1 = builder.prop1;
        this.prop2 = builder.prop2;
        this.prop3 = builder.prop3;
    }

    public class Builder { 
        private int prop1;
        private int prop2;
        private int prop3;
        public Builder prop1(int prop1) { this.prop1 = prop1; return this; } 
        public Builder prop2(int prop2) { this.prop2 = prop2; return this; } 
        public Builder prop3(int prop3) { this.prop3 = prop3; return this; } 

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

    }

    private class ChildObj extends ParentObj { 

    private final int prop4;
    private final int prop5;

    private ChildObj(ChildBuilder childBuilder) {
        super(childBuilder);

    }

    public class ChildBuilder extends Builder {
        private int prop4;
        private int prop5; 
        public ChildBuilder prop4(int prop4) { this.prop4 = prop4; return this; } 
        public ChildBuilder prop5(int prop5) { this.prop5 = prop5; return this; } 

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

1 个答案:

答案 0 :(得分:1)

可能最好的方法是覆盖父构建器方法。

class ChildBuilder {
  public ChildBuilder prop1(int prop1){ 
    return (ChildBuilder) super.prop1(prop1);
  }
}

虽然这不是很干净,但它可以用于你想要做的事情。