带继承的Java Builder模式

rad*_*dio 3 java inheritance design-patterns builder

我想实现一个带有静态内部类的构建器模式,比如说类A带有字段(a1,a2,a3),B带有字段(b1,b2),C带有字段(c1),而所有共享字段(s1,s2) )来自超级SuperClass:

public class A extends SuperClass {
    private final String a1;
    ...

    private A(ABuilder builder) {
        super(builder);
        this.a1 = builder.a1;
        ...
    }

    public static class ABuilder extends SuperClassBuilder implements ABuilderInterface {
        private String a1;
        ...

        @Override
        public ABuilder withA1(String a1) {
            this.a1 = a1;
            return this;
        }
        ...

        @Override
        public SuperClass build() {
            return new A(this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,对于B和C,构建器只是不同,它们有自己的字段并实现它们自己的接口(BBuilderInterface和CBuilderInterface),而这些接口只定义要实现的方法:

public interface ABuilderInterface extends SuperClassBuilderInterface {
    ABuilderInterface withA1(String a1);
    ...
}
...<interfaces for B and C>

public interface SuperClassBuilderInterface {
   SuperClassBuilderInterface withS1(String s1);
   ...
   SuperClass build();
}

// Usage of the builders:
public SuperClass foo() {
    return new A.ABuilder()
        .withA1(...) // returns ABuilderInterface
        ...
        .withS1(...) // returns SuperClassBuilderInterface
        ...
        .build();
}

public abstract class SuperClass {
private final String s1;
...

protected SuperClass(SuperClassBuilder builder) {
    this.s1 = builder.s1;
    ...
}

protected static abstract class SuperClassBuilder implements SuperClassBuilderInterface {
    private String s1;
    ...

    @Override
    public SuperClassBuilder withS1(String s1) {
        this.s1 = s1;
        return this;
    }
    ...

    @Override
    public abstract SuperClass build();
}
}
Run Code Online (Sandbox Code Playgroud)

现在你可以发现当我使用构建器时我必须注意首先调用与子类相关的with ...方法,然后将它们链接到超类,这不是一个大问题,但仍然不确定是否良好的做法.另一方面,我可以将子类的with ...方法一起添加到超类接口,然后限制消失,但后来我有一个混合了...的不同子类的方法.

你更喜欢/建议哪一个?

HTN*_*TNW 5

修改超类的构建器以使用F-bound(又名Curiously Recurring模板模式).

public interface SuperClassBuilderInterface<SELF extends SuperClassBuilderInterface<SELF>> {
    SELF withS1(String s1);
    // etc.
    Superclass build();
}
Run Code Online (Sandbox Code Playgroud)

然后你有:

class SuperClassBuilder<SELF extends SuperClassBuilder<SELF>> implements SuperClassBuilderInterface<SELF>

interface ABuilderInterface<SELF extends ABuilderInterface<SELF>> extends SuperClassBuilderInterface<SELF>

class ABuilder extends SuperClassBuilder<ABuilder> implements ABuilderInterface<ABuilder>
Run Code Online (Sandbox Code Playgroud)

注意,实现SuperClassBuilder必须包含未经检查的表单转换return (SELF)this;.类型系统在理论上是足够强大,不需要这个,但由此产生的编码可能会非常难看(见),它很可能不值得.

编辑:这是@shmosel的意思