构造不可变对象的抽象生成器

时间:2018-12-17 12:19:50

标签: java oop design-patterns reflection builder

我有以下代码实现抽象生成器(如有效的Java书中所述):

interface I {
    I ret();
}

abstract class A implements I {

    private String s = "";

    A(Builder b) {
        s = b.s;
    }

    @Override
    public I ret() {
        String s = "some new string from calc.";
        //HERE I NEED TO CONSTRUCT class B
        //THIS IS PROBLEMATIC LINE BELOW <<<<--------------------------------------
        return new Builder<>().withString(s).build();
    }

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

        String s = "";

        T withString(String s) {
            this.s = s;
            return self();
        }

        protected abstract A build();

        //simulated self-type idiom
        protected abstract T self();
    }
}

class B extends A {

    private B(A.Builder b) {
        super(b);
    }

    static class Builder extends A.Builder<Builder> {

        @Override
        protected B build() {
            return new B(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }
}

这是一个小用例

public static void main(String[] args) {
    I b = new B.Builder().withString("bclass").build();
    I b2 = b.ret(); //<---- this one should construct new immutable B
}

我想做的是-通过类ret()中的A方法,我想构造一个不了解父类型的不可变对象-因此在我的示例中,它将是新类{ {1}}具有新的内部字符串。

问题是类B不知道类A,因为B是它的父类。

在不求助于泛型的情况下,这样的事情是否可能?

如果我使用可变类,它将像B一样简单。

更新

this.s = newS;

1 个答案:

答案 0 :(得分:4)

您需要在A中提供一种抽象方法,以构建Builder的合适实例:

abstract Builder<A> toBuilder();

然后在具体的子类中实现它,并调用:

return toBuilder().withString(s).build();