我有两个构建器 - PayloadA
和PayloadB
。为了使示例更简单,我删除了许多其他字段。
PayloadA.Builder
构造函数将processName
,genericRecord
作为输入参数,然后从genericRecord
中提取一些内容。在那我正在做验证。PayloadB.Builder
构造函数也将processName
,genericRecord
作为输入参数,然后与上面的genericRecord
相比,它提取了一些不同的东西。在这些不同的领域,我正在进行验证。正如您所看到的,这两个Payload?.Builder
之间的共同点是processName
,genericRecord
,提取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 { ... }
然后,一旦我构建了我的构建器,我将把它传递给其他方法,并且我想使用getter访问所有字段。所以,让我们说我已经构建了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);
}
覆盖子类中的方法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());
}
访客模式可能令人难以招架。您也可以保持简单,并使用instanceof
来确定具体的类。
答案 1 :(得分:0)
我认为这里的问题是PayloadA和PayloadB是否正在为设计分享一些完全相同的东西。如果逻辑在某种程度上与一个参数相同,则可以有一个类。
也许您可以拥有抽象类,并且对于特定字段的实现,您可以返回特定实现的具体值。
例如,抽象类具有字段的抽象setter / getter,当您将该方法实现到PayloadA和PayloadB时,您可以返回所需的字段。
我认为问题在于设计在这里不是如何做到的。看看你的课程到底是什么,然后你有很多选择