静的内部クラスを持つビルダーパターンを実装して、クラスA(フィールドa1、a2、a3)、フィールドB(b1、b2)、フィールドC(フィールドc1)一方、スーパークラススーパークラスからすべての共有フィールド(S1、S2):継承を持つJava Builderパターン
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);
}
}
}
は、従って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();
}
}
これで、ビルダーを使用するときには、まず子クラスに関連するwith ...メソッドを呼び出してから、スーパークラスのものをチェーン化することに注意しなければならないという制限があります、しかし、まだ良い実践かどうかは分かりません。 反対側では、子クラスのwith ...メソッドをすべてスーパークラスインターフェイスに追加してから制限がなくなりましたが、別の子クラスの...メソッドと混在したインターフェイスがあります。
どちらをお好みですか/お勧めしますか?
'ABuilder'で' withS1() 'が返されますか? – alayor
@alayorまたはABuilderでは、親のものを使用しているため、withS1()はありません。アイデアは、A、B、Cビルダーには固有の...メソッドしかなく、共有ビルダーはスーパービルダーに残ります – radio
これは非常に一般的な問題です。 1つのパターンは、スーパークラスに汎用の「自己タイプ」を定義し、そのメソッドによって返されるパターンです。 – shmosel