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:
PayloadB
from upstream, then I want key
field in the Payload
class to be whatever is the value of type
in PayloadB
class in all lower case and if we get PayloadA
from upstream, then I want key to be world
.PayloadB
from upstream and if clientId
was set, then I want partition
to be 15
and if we get PayloadA
from upstream and if clientId
was set then I want partition
to be 15
but if it was not set and langId
was there, then I want partition
to be 17
.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?
builder
instance to the PayloadX
constructor. Either pass values as individual constructor arguments or call setters.Payload.Builder
which would hold common fields of PayloadA
and PayloadB
. This class will be an abstract class declaring an abstract build
method.PayloadA.Builder
and PayloadB.Builder
will extend Payload.Builder
, implementing the build
method.build
method you implement whatever custom logic you need to create and set the fields of the PayloadX
.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()
.