[英]Subclassing abstract class in a builder pattern?
我有两种类型的有效负载来自上游: PayloadA
或PayloadB
。 与PayloadB
相比, PayloadA
具有许多字段,但是PayloadA
和PayloadB
之间有一些公共字段。 为了简化示例,我仅添加了几个字段。
以下是PayloadA
的构建器类:
public final class PayloadA {
private final String clientId;
private final String langid;
private final String deviceId;
private final Map<String, String> applicationPayload;
// other fields as well
private PayloadA(Builder builder) {
this.clientId = builder.clientId;
this.langid = builder.langid;
this.deviceId = builder.deviceId;
this.applicationPayload = builder.applicationPayload.build();
}
public static class Builder {
protected final String deviceId;
protected String clientId;
protected String langid;
protected ImmutableMap.Builder<String, String> applicationPayload = ImmutableMap.builder();
public Builder(String deviceId) {
this.deviceId = deviceId;
}
public Builder setClientId(String clientId) {
this.clientId = clientId;
return this;
}
public Builder setLangid(String langid) {
this.langid = langid;
return this;
}
public Builder setPayload(Map<String, String> payload) {
this.applicationPayload.putAll(payload);
return this;
}
public PayloadA build() {
return new PayloadA(this);
}
}
// getters and to string here
}
现在下面是PayloadB
的类:
public final class PayloadB {
private final String clientid;
private final String type;
private final String payId;
// other fields as well
private PayloadB(Builder builder) {
this.clientid = builder.clientid;
this.type = builder.type;
this.payId = builder.payId;
}
public static class Builder {
protected final String type;
protected String payId;
protected String clientid;
public Builder(String type) {
this.type = type;
}
public Builder setPayId(String payId) {
this.payId = payId;
return this;
}
public Builder setClientId(String clientid) {
this.clientid = clientid;
return this;
}
public PayloadB build() {
return new PayloadB(this);
}
}
// getters and to string here
}
现在,我创建了另一个类,即Payload
类,其中具有PayloadA
和PayloadB
所有公共字段,因此我也必须以某种方式设置这些字段,而且我不确定如何在下面的类中使用:
public abstract class Payload {
private long createTimestamp;
private String key;
// some other fields are here
// getters and setters here
}
题:
现在,从下面的代码中,我根据传递的内容来PayloadA
或PayloadB
。
private void run(String name) {
// .. some code here
if (name.equalsIgnoreCase("PayloadA")) {
Payload payload =
new PayloadA.Builder(getDeviceId()).setClientId("someid").setLangid("anotherid")
.setPayload("some map").build();
DataProcessor.getInstance().process(payload);
} else {
Payload payload =
new PayloadB.Builder(getType()).setPayId("someid").setClientId("anotherid").build();
DataProcessor.getInstance().process(payload);
}
}
并在DataProcessor
process
方法中:
private void process(Payload payload) {
// 1) here I need to set createTimestamp and key variables on payload bcoz they are common
// fields.
// 2) Also how can I figure out whether payload is PayloadA or PayloadB here?
}
现在如何在process
方法的Payload
类中设置createTimestamp
和key
变量? 现在,我有一个区分的运行方法,但是通常我将为PayloadA使用不同的上游代码,为PayloadB使用不同的上游代码,因此我们将使用其中一个Payload类。
另外,我应该在这里安排两名不同的建筑商,还是在这里一名大型建筑商?
PayloadA
和PayloadB
可以如下所示扩展Payload
:
public abstract class Payload {
private long createTimestamp;
private String key;
// some other fields are here
// getters and setters here
}
public class PayloadA extends Payload {
//add existing code
}
public class PayloadB extends Payload {
//add existing code
}
private void process(Payload payload) {
//Depending upon the object passed, fields will be set for A or B
payload.setCreateTimestamp(ADD_DATA1);
payload.setKey(ADD_DATA2);
//set other fields
//if(payload instanceof PayloadA) {
//payloadA
//}
}
如何确定有效载荷是
process()
内的PayloadA
还是PayloadB
?
您可以发现使用instanceof
就像上面所示的PayloadA
payload
instanceof
一样。 但是,通常来说,使用instanceof
检查进行编码不是一个好主意,因此除非无法避免,否则不要使用它。
我应该在这里安排两名不同的建设者,还是在其中一名大型建设者?
根据上面提供的代码,这些字段的PayloadA
和PayloadB
不同,因此最好保留单独的bean和相应的构建器。
更新:我需要弄清楚它是什么类型的有效载荷,并基于此我需要为键变量设置值?
里面setKey()
将调用传递给对象类型process(Payload payload)
(多态性的OOP的基本原则之一),即,如果传递PayloadA
从对象run()
方法, setKey()
上PayloadA
对象将叫做。 总而言之,您根本不需要instanceof
检查。 由您决定要在哪里设置密钥,可以在process()
方法内部(如果您还有其他依赖项来生成key
),也可以按照@Roberto的建议进行操作
abstract public class Payload {
abstract void setKey();
}
public class PayloadA extends Payload {
//add existing code
void setKey() {
key = "a";
}
}
public class PayloadB extends Payload {
//add existing code
void setKey() {
key = "b";
}
}
private void process(Payload payload) {
//Depending upon the object passed, fields will be set for A or B
payload.setCreateTimestamp(ADD_DATA1);
payload.setKey();
}
编辑 :
这里的想法是任何扩展有效载荷的类都必须实现setKey()方法,或者必须是抽象的。 因此,PayloadA和PayloadB都实现了该方法。 每个类提供不同的实现。
现在假设你做
PayloadA pa = new PayloadA();
pa.setKey()
不出所料,实际执行的实现将是PayloadA中定义的实现。
现在考虑这种情况:
Payload pa = new PayloadA();
pa.setKey()
尽管声明了变量的类型为Payload,但是变量所引用的对象的实际类型为PayloadA,因此setKey()调用是PayloadA中的对象。 这称为动态调度,因为在运行时(而不是在编译时)知道调用的实现
public class Payload {
// common fields
private String clientid;
private String key;
private long Timestamp;
// setter and getters
}
public class PayloadA extends Payload implements PayloadStrategy {
// PayloadA specific fields
private String langid;
private String deviceId;
// setters and getters
public static class Builder {
// existing code
}
@Override
public void process() {
System.out.println("PayloadA specific implementation");
}
}
public class PayloadB extends Payload implements PayloadStrategy {
// PayloadA specific fields
private String type;
private String payId;
// setters and getters
public static class Builder {
// existing code
}
@Override
public void process() {
System.out.println("PayloadB specific implementation");
}
}
}
// define contract
public interface PayloadStrategy {
public void process();
}
// payload context
public class PayloadContext {
PayloadStrategy strategy;
public void setContext(PayloadStrategy payloadStrategy) {
this.strategy = payloadStrategy;
}
public void processPayload() {
strategy.process();
}
}
// parameterized (PayloadA or PayloadB) payload run method
PayloadContext context = new PayloadContext();
context.setContext(new PayloadA());
context.processPayload();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.