具有非平凡子类树的Java构建器模式 [英] Java builder pattern with non-trivial subclass tree

查看:65
本文介绍了具有非平凡子类树的Java构建器模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我熟悉将生成器模式与泛型和子类一起使用,但是我看不到如何使其与不平凡的子类树一起使用(即C扩展B扩展了A扩展)。以下是我要执行的操作的一个简单示例:

I'm familiar with using the builder pattern with generics and subclassing, but I can't see how to make it work with a non-trivial tree of subclasses (i.e. C extends B extends A). Here's a simple example of what I'm trying to do:

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:

Everything is fine if I declare BBuilder without the generic type:

public static class BBuilder extends ABuilder<BBuilder>

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

Since I want BBuilder to be extended by a CBuilder, I'm trying to use the same sort of Curiously Recurring Template Pattern as ABuilder. But like this, the compiler sees BBuilder.withValue() as returning an ABuilder, not a BBuilder as I want. This:

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

不编译。谁能看到我在这里做错的事情,我一直在尝试各种不同的泛型模式,但无法正常工作。

doesn't compile. Can anyone see what I'm doing wrong here, I've been going round trying different patterns of generics but can't get it to work.

感谢任何人有任何建议。

Thanks to anyone who has any advice.

推荐答案

似乎您的错误仅在于声明正确的参数:

It seems that your mistake only with declaring correct parameter:

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

这篇关于具有非平凡子类树的Java构建器模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆