问题
I have two types of payload coming from upstream: It's either PayloadA
or PayloadB
. There are some common fields between PayloadA
and PayloadB
so I created Payload
class with those common fields and for rest I created two builder class one for each payload.
Below is the builder class for PayloadA
:
public final class PayloadA {
private final String clientId;
private final String langid;
private final String deviceId;
private final Map<String, String> applicationPayload;
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
}
Now below is the class for PayloadB
:
public final class PayloadB {
private final String clientid;
private final String type;
private final String payId;
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
}
Now I have created another class which is Payload
class (does this have to be abstract class?) in which I have all the common fields both for PayloadA
and PayloadB
so I have to set these fields as well somehow and I am not sure how to use below class:
public abstract class Payload {
private long createTimestamp;
private String partition;
private String key;
// some other fields here
// getters and setters here
}
Question:
- Now let's say if we get
PayloadB
from upstream, then I wantkey
field in thePayload
class to be whatever is the value oftype
inPayloadB
class in all lower case and if we getPayloadA
from upstream, then I want key to beworld
. - And also if we get
PayloadB
from upstream and ifclientId
was set, then I wantpartition
to be15
and if we getPayloadA
from upstream and ifclientId
was set then I wantpartition
to be15
but if it was not set andlangId
was there, then I wantpartition
to be17
. - And I want to set
createTimestamp
as well which I have to do after building a Payload object. So for example I have build PayloadA object and it will be passed to some other class and there I need to set createTimestamp value on PayloadA object. Not sure how to do that as well? Do I have to clone something?
How can I use Payload
class in my builder pattern? I will get two different payloads and there will be few things common in them so common fields I have separated them out in an abstract class.
Should I have on big builder pattern class with everything in it or multiple builder pattern extending something?
回答1:
- I won't pass
builder
instance to thePayloadX
constructor. Either pass values as individual constructor arguments or call setters. - You can define
Payload.Builder
which would hold common fields ofPayloadA
andPayloadB
. This class will be an abstract class declaring an abstractbuild
method. PayloadA.Builder
andPayloadB.Builder
will extendPayload.Builder
, implementing thebuild
method.- In this
build
method you implement whatever custom logic you need to create and set the fields of thePayloadX
.
It seems like you want to make your class immutable (careful with applicationPayload
by the way). In this case you can't really "set" anything. You can only produce a new instance. There are many ways to do this, for instance you can implement PayloadX withTimestamp(...)
method. Or you can extend your build to accept PayloadX
and set timestamp there, resulting in something like new PayloadX.Builder(payloadXInstance).setTimestamp(...).build()
.
来源:https://stackoverflow.com/questions/40990829/usage-of-abstract-class-in-the-builder-pattern