具有非平凡子类树的Java builder模式

具有非平凡子类树的Java builder模式,java,generics,builder,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 sta

我熟悉将生成器模式用于泛型和子类,但我看不出如何使其与非平凡的子类树(即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);
        }
    }
}
不编译。有人能看出我做错了什么吗?我一直在尝试不同的泛型模式,但都没能成功


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

看来您的错误只是声明了正确的参数:

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);
        }
    }
}

你确定你需要仿制药吗?如果没有泛型,这种层次结构似乎可以正常工作

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);
}

“既然我希望BBuilder由CBuilder扩展,“为什么?”
公共静态类ABuilder{…}
”-您如何在不使用子类化和原始类型的情况下正确定义该类型的变量?--“
返回新的BBuilder();
”-这是一个原始类型。无论如何。。您不需要任何泛型,因为返回实例将始终是的子类ABuilder@MarcosVasconcelos问题在于方法链接:如果在
BBuilder
上调用源于
ABuilder
的方法,方法的返回类型将是一个
ABuilder
,因此您限制了对可以从那里调用的方法的访问。。确实,我错过了ABuilder方法将返回ABuilder,这是一个很好的解决方案。两个问题:有没有办法删除对
T
的强制转换
returnnewbuilder()的推断类型是什么builder()
-methods中的code>?是否有任何方法可以删除对T的强制转换-使用这种方法-而不是。也许不做生成器继承会更好。return new Builder()的推断类型是什么<代码>?扩展B.Builder
?扩展B.Builder
”-有趣的是:如果用此类型替换菱形运算符,将得到编译器错误:
错误:意外类型。。。必需:类或接口没有边界。。。发现:?扩展生成器
。在写这里之前,我已经检查了此代码。我没有任何编译错误,甚至没有警告。您可以检查它。:-)尝试复制粘贴它并在IDE中运行。我想你会得到同样的结果。你的代码是正确的。但您提供的推断类型不是。到目前为止,我无法在diamond中声明任何可以编译的类型。唯一需要编译的是菱形和原始类型。这个问题并不重要,我只是好奇而已。这种方法有一个缺点,就是你不得不用(所有)父类的…(…)-方法覆盖所有
,并用样板代码填充这些方法。否则,方法链接将中断。@Turing85-我看不到这一点。查看我如何在
C
中未使用值覆盖
。也许你可以进一步解释。@Turing85-哦,等等-我明白你的意思了-调用
CBuilder.withValue
返回一个
BBuilder
-所以我同意没有那么有用。
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();
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);
}