1

我有兩個建設者 - PayloadAPayloadB。爲了讓示例更簡單,我刪除了很多其他字段。如何繼承Java構建器類?

  • PayloadA.Builder構造函數採用processNamegenericRecord作爲輸入參數,然後從提取genericRecord幾件事情。並且我正在進行驗證。
  • PayloadB.Builder構造函數也需要processName,genericRecord作爲輸入參數,然後從genericRecord中提取幾個不同的東西,與上面相比。在這些不同的領域,我正在進行驗證。

正如你可以看到,這兩個Payload?.Builder之間的共同點是processNamegenericRecord,提取oldTimestamp值,然後isValid方法。

下面是我的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

只有當提到的字段不重合時才爲有效載荷創建超類。您可以在其中移動常用字段和方法(但不包括構建器)。你甚至可以爲建設者創建一個超級類,但它可能會使代碼太多。

如果你真的有有效載荷的超類中的使用,那麼你可以實現你的execute方法與Visitor Pattern

首先,你必須創建一個遊客在這裏你可以訪問你的具體類:

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

覆蓋的方法accept在子類:

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

你的方法execute調用只是重定向到根據visit方法:

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

Visitor模式可以是壓倒性的。您也可以保持簡單並使用instanceof來確定具體的類別。

+0

我將能夠訪問執行中的PayloadA或PayloadB的所有字段方法呢?我對這一部分感到困惑。 – john

+0

不,您不能在'execute'方法中訪問'PayloadA'或'PayloadB'的字段。但是'execute'方法由於延遲綁定而調用'PayloadA'或'PayloadB'的accept方法。 'accept'方法反過來調用超載的'visit'方法。在'visit'方法中,您可以訪問特定的字段,這就是您編寫代碼的地方。 –

0

我認爲這裏的問題是PayloadA和PayloadB是否共享設計的完整意義。如果邏輯除了一個參數以外是相同的,那麼你可以有一個類。

也許你可以擁有抽象類,並且對於特定字段的實現,你可以返回具體值的具體實現。

例如,抽象類具有字段的抽象setter/getter,當您將該方法實現到PayloadA和PayloadB時,您可以返回所需的字段。

我認爲問題是這裏的設計不是如何去做。看看你的類真的是什麼,然後你有很多選擇