1

私は2人のビルダー - PayloadAPayloadBを持っています。例を簡単にするために、私は他の多くのフィールドを削除しました。Javaビルダークラスをサブクラス化する方法は?

  • PayloadA.Builderコンストラクタは、入力パラメータとしてprocessNamegenericRecordを取り、その後、genericRecordからいくつかを抽出します。そしてその上で私は検証をしています。
  • PayloadB.BuilderコンストラクタもprocessName,genericRecordを入力パラメータとし、上記と比較してgenericRecordからわずかな異なるものを抽出します。そしてそれらの異なる分野で私は検証を行っています。

あなたが見ることができるように、これら2 Payload?.Builder間の共通点はoldTimestamp値、その後isValid方法を抽出し、processNamegenericRecordです。以下は

は私PayloadAクラスです:

以下
public final class PayloadA { 
    private final String clientId; 
    private final String deviceId; 
    private final String processName; 
    private final GenericRecord genericRecord; 
    private final Long oldTimestamp; 

    private PayloadA(Builder builder) { 
    this.clientId = builder.clientId; 
    this.deviceId = builder.deviceId; 
    this.processName = builder.processName; 
    this.genericRecord = builder.genericRecord; 
    this.oldTimestamp = builder.oldTimestamp; 
    } 

    public static class Builder { 
    private final String processName; 
    private final GenericRecord genericRecord; 
    private final String clientId; 
    private final String deviceId; 
    private final Long oldTimestamp; 

    public Builder(PayloadA payload) { 
     this.processName = payload.processName; 
     this.genericRecord = payload.genericRecord; 
     this.clientId = payload.clientId; 
     this.deviceId = payload.deviceId; 
     this.oldTimestamp = payload.oldTimestamp; 
    } 

    public Builder(String processName, GenericRecord genericRecord) { 
     this.processName = processName; 
     this.genericRecord = genericRecord; 
     this.clientId = (String) DataUtils.parse(genericRecord, "clientId"); 
     this.deviceId = (String) DataUtils.parse(genericRecord, "deviceId"); 
     this.oldTimestamp = (Long) DataUtils.parse(genericRecord, "oldTimestamp"); 
    } 

    // calling this method to validate 
    public boolean isValid() { 
     return isValidClientIdDeviceId(); 
    } 

    private boolean isValidClientIdDeviceId() { 
     // validate here 
    } 

    public PayloadA build() { 
     return new PayloadA(this); 
    } 
    } 

    // getter here 
} 

PayloadBクラスは次のとおりです。

public final class PayloadB { 
    private final GenericRecord genericRecord; 
    private final String processName; 
    private final String type; 
    private final String datumId; 
    private final Long oldTimestamp; 

    private PayloadB(Builder builder) { 
    this.processName = builder.processName; 
    this.genericRecord = builder.genericRecord; 
    this.type = builder.type; 
    this.datumId = builder.datumId; 
    this.oldTimestamp = builder.oldTimestamp; 
    } 

    public static class Builder { 
    private final GenericRecord genericRecord; 
    private final String processName; 
    private final String type; 
    private final String datumId; 
    private final Long oldTimestamp; 

    public Builder(PayloadB payload) { 
     this.processName = payload.processName; 
     this.genericRecord = payload.genericRecord; 
     this.type = payload.type; 
     this.datumId = payload.datumId; 
     this.oldTimestamp = payload.oldTimestamp; 
    } 

    public Builder(String processName, GenericRecord genericRecord) { 
     this.processName = processName; 
     this.genericRecord = genericRecord; 
     this.type = (String) DataUtils.parse(genericRecord, "type"); 
     this.datumId = (String) DataUtils.parse(genericRecord, "datumId"); 
     this.oldTimestamp = (Long) DataUtils.parse(genericRecord, "oldTimestamp"); 
    } 

    // calling this method to validate 
    public boolean isValid() { 
     return isValidType() && isValidDatumId(); 
    } 

    private boolean isValidType() { 
     // validate here 
    } 

    private boolean isValidDatumId() { 
     // validate here 
    } 

    public PayloadB build() { 
     return new PayloadB(this); 
    } 
    } 

    // getter here 

} 

今、私はここに抽象クラスの概念を使用することができますどのような方法がありますか?私は抽象クラスPayloadを作成することができますが、何が私の抽象クラス内のものでなければなりません:

public final class PayloadA extends Payload { ... } 
public final class PayloadB extends Payload { ... } 

そして、私は両方の私のビルダーを構築したら、その後、私はいくつかの他のメソッドに渡しますし、そこに私はすべてにアクセスしたいですgettersを使ってフィールドを作成します。だから私がPayloadAをビルドしているので、以下に示すようにメソッドを実行して、そのメソッドで、PayloadAのすべてのフィールドを抽出したいとします。同様にメソッドを実行するためにPayloadBを送信する場合、getterを使用してPayloadBクラスのすべてのフィールドを抽出します。これどうやってするの?

private void execute(Payload payload) { 

    // How can I access fields of PayloadA or PayloadB 
    // depending on what was passe 
} 
+0

*私の抽象クラスの中に何があるべきでしょうか*両方のものに共通するもの –

答えて

1

上記のフィールドが一致しない場合にのみ、ペイロードのスーパークラスを作成します。共通のフィールドとメソッド(ビルダーではない)をそこに移動することができます。あなたはビルダーのためのスーパークラスを作ることさえできるかもしれませんが、おそらくコードをあまりにも乱雑にするでしょう。

あなたが本当にペイロードのスーパークラスの使用を持っているなら、あなたはVisitor Patternとあなたのexecuteメソッドを実装することができます

まず、あなたがあなたの具体的なクラスにアクセスすることができ、訪問者を作成する必要があります。

public class PayloadVisitor { 

    public void visit(PayloadA payloadA) { 
     // use payload A here 
    } 

    public void visit(PayloadB payloadB) { 
     // use payload B here 
    } 
} 

次にあなたが訪問者を受け入れ、あなたのスーパークラスにメソッドを追加する必要があります。

public abstract class Payload { 

    // common fields and methods 

    public abstract void accept(PayloadVisitor visitor); 
} 

は、メソッドをオーバーライドサブクラスで:ビジターパターンが圧倒的なことができ

private void execute(Payload payload) { 
    payload.accept(new PayloadVisitor()); 
} 

:ちょうど従っvisitメソッドへのコールをリダイレクトexecute

public final class PayloadA extends Payload { 

    // ... 

    @Override 
    public void accept(PayloadVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

public final class PayloadB extends Payload { 

    // ... 

    @Override 
    public void accept(PayloadVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

あなたの方法。また、単純なままにして、instanceofを使用して具体的なクラスを決定することもできます。

+0

実行時にPayloadAまたはPayloadBのすべてのフィールドにアクセスできますか?方法?私はその部分を混乱させる。 – john

+0

いいえ、 'execute'メソッドの' PayloadA'または 'PayloadB'のフィールドにアクセスすることはできません。しかし、 'execute'メソッドは、' PayloadA'または 'PayloadB'の' accept'メソッドを遅いバインディングのために呼び出します。 'accept'メソッドは、オーバーロードされた' visit'メソッドを呼び出します。 'visit'メソッドの中では、特定のフィールドにアクセスすることができ、これはあなたのコードを書く場所です。 –

0

PayloadAとPayloadBがデザインに完全な意味を共有しているとします。 1つのパラメータを除いてロジックが何とか同じ場合、1つのクラスを持つことができます。

抽象クラスを持つことができます。特定のフィールドの実装では、特定の実装の具体的な値を返すことができます。

たとえば、抽象クラスにはフィールドの抽象セッタ/ゲッターがあり、そのメソッドをPayloadAおよびPayloadBに実装すると、必要なフィールドを返すことができます。

私はこの問題はデザイン方法ではないと思います。あなたのクラスが本当に何であるかを見て、次に多くのオプションを持っているのを見てください

関連する問題