У меня есть класс строителя, который я использую в одном из моих проектов.Как клонировать старый строитель, чтобы создать новый объект-строитель?
- Предположим, у меня есть
metricA
как строитель, основанный на классе ниже. - мне нужно сделать новый построитель
metricB
, основанного наmetricA
клонированииmetricA
так, чтоmetricB
содержит все значения, которые были там уже вmetricA
.
В конструкторе MetricHolder
Я инициализирую некоторые поля (которые не заданы непосредственно) в соответствии с уже установленными полями.
clientTypeOrPayId
- Я инициализирую это поле. Если присутствуетpayId
, тогда я установил это значение или установилclientType
.clientKey
- Я инициализирую это поле также в том же конструкторе.- И самое главное, я помещаю несколько обязательных полей на карте
clientPayload
. Я не уверен, что это правильный способ сделать это. Но мне нужно добавитьis_clientid
иis_deviceid
на карту. (В общем, я добавляю несколько полей). - И затем в последнем из конструкторов я вычисляю разницу в задержках и отправляю ее в какую-то другую систему.
Ниже мой класс:
public final class MetricHolder {
private final String clientId;
private final String deviceId;
private final String payId;
private final String clientType;
private final String clientTypeOrPayId;
private final Schema schema;
private final String schemaId;
private final String clientKey;
private final Map<String, String> clientPayload;
private final Record record;
private final long clientCreateTimestamp;
private final long clientSentTimestamp;
private MetricHolder(Builder builder) {
this.payId = builder.payId;
this.siteId = builder.siteId;
this.clientType = builder.clientType;
this.clientId = builder.clientId;
this.deviceId = builder.deviceId;
this.schema = builder.schema;
this.schemaId = builder.schemaId;
// populating all the required fields in the map and make it immutable
// not sure whether this is right?
builder.clientPayload.put("is_clientid", (clientId == null) ? "false" : "true");
builder.clientPayload.put("is_deviceid", (clientId == null) ? "true" : "false");
this.clientPayload = Collections.unmodifiableMap(builder.clientPayload);
this.clientTypeOrPayId = Strings.isNullOrEmpty(payId) ? clientType : payId;
this.record = builder.record;
this.clientKey = "process:" + System.currentTimeMillis() + ":"
+ ((clientId == null) ? deviceId : clientId);
this.clientCreateTimestamp = builder.clientCreateTimestamp;
this.clientSentTimestamp = builder.clientSentTimestamp;
// this will be called twice while cloning
// what is the right way to do this then?
SendData.getInstance().insert(clientTypeOrPayId,
System.currentTimeMillis() - clientCreateTimestamp);
SendData.getInstance().insert(clientTypeOrPayId,
System.currentTimeMillis() - clientSentTimestamp);
}
public static class Builder {
private final Record record;
private Schema schema;
private String schemaId;
private String clientId;
private String deviceId;
private String payId;
private String clientType;
private Map<String, String> clientPayload;
private long clientCreateTimestamp;
private long clientSentTimestamp;
// this is for cloning
public Builder(MetricHolder packet) {
this.record = packet.record;
this.schema = packet.schema;
this.schemaId = packet.schemaId;
this.clientId = packet.clientId;
this.deviceId = packet.deviceId;
this.payId = packet.payId;
this.clientType = packet.clientType;
// make a new map and check whether mandatory fields are present already or not
// and if they are present don't add it again.
this.clientPayload = new HashMap<>();
for (Map.Entry<String, String> entry : packet.clientPayload.entrySet()) {
if (!("is_clientid".equals(entry.getKey()) || "is_deviceid".equals(entry.getKey())) {
this.clientPayload.put(entry.getKey(), entry.getValue());
}
}
this.clientCreateTimestamp = packet.clientCreateTimestamp;
this.clientSentTimestamp = packet.clientSentTimestamp;
}
public Builder(Record record) {
this.record = record;
}
public Builder setSchema(Schema schema) {
this.schema = schema;
return this;
}
public Builder setSchemaId(String schemaId) {
this.schemaId = schemaId;
return this;
}
public Builder setClientId(String clientId) {
this.clientId = clientId;
return this;
}
public Builder setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public Builder setPayId(String payId) {
this.payId = payId;
return this;
}
public Builder setClientType(String clientType) {
this.clientType = clientType;
return this;
}
public Builder setClientPayload(Map<String, String> payload) {
this.clientPayload = payload;
return this;
}
public Builder setClientCreateTimestamp(long clientCreateTimestamp) {
this.clientCreateTimestamp = clientCreateTimestamp;
return this;
}
public Builder setClientSentTimestamp(long clientSentTimestamp) {
this.clientSentTimestamp = clientSentTimestamp;
return this;
}
public MetricHolder build() {
return new MetricHolder(this);
}
}
// getters
}
Вопрос: -
Ниже, как я делаю metricA
строитель объекта:
MetricHolder metricA = new MetricHolder.Builder(record).setClientId("123456").setDeviceId("abcdefhg")
. setPayId("98765").setClientPayload(payloadMapHolder).setClientCreateTimestamp(createTimestamp)
.setClientSentTimestamp(sentTimestamp).build();
Теперь это, как я клонировать metricA
объект позже в коде, когда я получаю все остальные поля DS, как показано ниже:
MetricHolder metricB = new MetricHolder.Builder(metricA).setSchema(schema).setSchemaId("345").build();
Я вижу две проблемы сейчас:
- Прежде всего, моя
SendData.getInstance()
линия вMetricHolder
конструктор будет вызываться дважды. Во-первых, когда я делаюmetricA
и второй, когда делаюmetricB
, клонируяmetricA
. Но я просто хочу назвать это только один раз при попытке создатьmetricA
объект-строитель? Как я могу сделать это возможным? - Во-вторых, путь, который я заполняю
clientPayload
Карта с двумя обязательными полями в конструктореMetricHolder
выглядит не так. Есть ли другой лучший способ сделать то же самое?
Я предполагаю, что вся проблема происходит потому, что так, как я клонировать metricA
сделать объект metricB
строителя? Каков наилучший способ сделать это? Я хочу достичь выше двух вещей, но правильно.
Ваш вопрос неясен, потому что в нем много ненужного материала (много полей и сеттеров и т. Д., Которые не выглядят релевантными). Пожалуйста, вы можете разделить его на [mcve], чтобы ключевые части вашего кода были более очевидными? –