具有非平凡子类树的

时间:2018-06-13 13:53:01

标签: java generics builder

我熟悉使用构建器模式和泛型和子类化,但我不知道如何使它与非平凡的子类树一起工作(即C扩展B扩展A)。这是我尝试做的一个简单示例:

class A {
    private final int value;

    protected A(ABuilder builder) {
        this.value = builder.value;
    }

    public int getValue() { return value; }

    public static class ABuilder<T extends ABuilder<T>> {
        private int value;

        public T withValue(int value) {
            this.value = value;
            return (T) this;
        }

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

class B extends A {
    private final String name;

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

    protected B(BBuilder builder) {
        super(builder);
        this.name = builder.name;
    }

    public String getName() { return name; }

    public static class BBuilder<U extends BBuilder<U>> extends ABuilder<BBuilder<U>> {
        private String name;

        public U withName(String name) {
            this.name = name;
            return (U) this;
        }

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

如果我在没有通用类型的情况下声明BBuilder,那么一切都很好:

public static class BBuilder extends ABuilder<BBuilder>

由于我希望BBuilder能够被CBuilder扩展,我试图使用与ABuilder相同的奇怪重复模板模式。但是像这样,编译器将BBuilder.withValue()视为返回ABuilder,而不是我想要的BBuilder。这样:

    B b = builder.withValue(1)
    .withName("X")
    .build();

没有编译。任何人都可以看到我在这里做错了什么,我一直在尝试不同的仿制药模式,但无法让它发挥作用。

感谢任何有任何建议的人。

2 个答案:

答案 0 :(得分:1)

似乎你的错误只是声明了正确的参数:

class A {

    private final int value;

    public static <T extends Builder<T>> T builderA() {
        return (T)new Builder<>();
    }

    protected A(Builder<? extends Builder<?>> builder) {
        value = builder.value;
    }

    public static class Builder<T extends Builder<T>> {

        private int value;

        public T withValue(int value) {
            this.value = value;
            return (T)this;
        }

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

class B extends A {

    private final String name;

    public static <T extends Builder<T>> T builderB() {
        return (T)new Builder<>();
    }

    protected B(Builder<? extends Builder<?>> builder) {
        super(builder);
        name = builder.name;
    }

    public static class Builder<T extends Builder<T>> extends A.Builder<T> {

        private String name;

        public Builder<T> withName(String name) {
            this.name = name;
            return this;
        }

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

客户代码:

A a = A.builder().withValue(1).build();
B b = B.builder().withValue(2).withName("xx").build();

答案 1 :(得分:0)

您确定需要仿制药吗?这种层次结构在没有泛型的情况下似乎工作正常。

static class A {
    protected final int value;

    protected A(ABuilder builder) {
        this.value = builder.value;
    }

    public int getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "A{" +
                "value=" + value +
                '}';
    }

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

    public static class ABuilder {
        protected int value;

        public ABuilder withValue(int value) {
            this.value = value;
            return this;
        }

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

}

static class B extends A {
    protected final String name;

    protected B(BBuilder builder) {
        super(builder);
        this.name = builder.name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "B{" +
                "value=" + value +
                ", name='" + name + '\'' +
                '}';
    }

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

    public static class BBuilder extends ABuilder {
        private String name;

        public BBuilder withName(String name) {
            this.name = name;
            return this;
        }

        @Override
        public BBuilder withValue(int value) {
            this.value = value * 2;
            return this;
        }

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

static class C extends B {
    private final String otherName;

    protected C(CBuilder builder) {
        super(builder);
        this.otherName = builder.otherName;
    }

    public String getName() {
        return otherName;
    }

    @Override
    public String toString() {
        return "C{" +
                "value=" + value +
                ", name='" + name + '\'' +
                ", otherName='" + otherName + '\'' +
                '}';
    }

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

    public static class CBuilder extends BBuilder {
        private String otherName;

        public CBuilder withName(String name) {
            this.otherName = name;
            return this;
        }

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

public void test() {
    A a = A.builder().withValue(10).build();
    B b = B.builder().withValue(10).withName("B").build();
    C c = C.builder().withName("C").build();
    System.out.println("a = "+a);
    System.out.println("b = "+b);
    System.out.println("c = "+c);
}