2016-12-06 13 views
0

У меня есть два типа полезной нагрузки, исходящих из восходящего потока: это либо PayloadA, либо PayloadB. Есть несколько общих полей между PayloadA и PayloadB, поэтому я создал класс Payload с этими общими полями, и для отдыха я создал два класса построек для каждой полезной нагрузки.Использование абстрактного класса в шаблон строителя?

Ниже класс строитель для 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 
} 

Теперь ниже класс для 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 
} 

Теперь я создал еще один класс, который Payload класс (это имеет быть абстрактный класс?), в котором у меня есть все общие поля как для PayloadA, так и для PayloadB, поэтому я должен как-то установить эти поля, и я не уверен, как использовать ниже класс:

public abstract class Payload { 
    private long createTimestamp; 
    private String partition; 
    private String key; 
    // some other fields here 

    // getters and setters here 
} 

Вопрос:

  • Теперь, скажем, если мы получим PayloadB от входа, то я хочу key поле в Payload классе, чтобы быть все, что значение type в PayloadB классе всего ниже и если мы получим PayloadA с восходящего потока, тогда я хочу, чтобы ключ был world.
  • А также, если мы получим PayloadB от входа, и если clientId был установлен, то я хочу partition быть 15 и если мы получим PayloadA от входа, и если clientId был установлен, то я хочу partition быть 15, но если он не был установлен и langId был там, тогда я хочу partition быть 17.
  • И я хочу установить createTimestamp, что я должен сделать после создания объекта полезной нагрузки. Так, например, я создал объект PayloadA, и он будет передан другому классу, и мне нужно установить значение createTimestamp на объект PayloadA. Не знаете, как это сделать? Нужно ли мне клонировать что-то?

Как я могу использовать класс Payload в моем шаблоне построения? Я получу две разные полезные нагрузки, и в них будет так много общих разделов, что я выделил их в абстрактном классе.

Должен ли я иметь класс шаблонов большого строителя со всем, что в нем, или с несколькими шаблонами-строителями, расширяющими что-то?

+1

Для начала, почему вы используете строителей? Похоже, что код перепроектирован ... – Spotted

+0

В общем, у всех этих полезных нагрузок много полей. Чтобы сделать пример проще понять, я сделал это так. – john

+0

Итак, вы представили строителей из-за огромных классов. Вы уже рассматривали рефакторинг в меньших классах, тем самым разрешая * корень * проблемы? На данный момент ваша проблема звучит для меня как [XYProblem] (http://xyproblem.info/): вы спрашиваете, как использовать абстрактный класс в построителе (что-то очень необычное), а не спрашивать себя «почему я закончилась в такой странной конструкции? " – Spotted

ответ

1
  • Я не буду передавать builder экземпляр на конструктор PayloadX. Либо передайте значения как индивидуальные аргументы конструктора, либо определители вызовов.
  • Вы можете определить Payload.Builder, где будут храниться общие поля PayloadA и PayloadB. Этот класс будет абстрактным классом, объявляющим абстрактный метод build.
  • PayloadA.Builder и PayloadB.Builder будет распространяться Payload.Builder, реализуя метод build.
  • В этом методе build вы реализуете любую настраиваемую логику, которую необходимо создать, и задайте поля PayloadX.

Похоже, вы хотите сделать свой класс непреложным (кстати, с осторожностью с applicationPayload). В этом случае вы ничего не можете «установить». Вы можете создать только новый экземпляр. Существует много способов сделать это, например, вы можете реализовать метод PayloadX withTimestamp(...). Или вы можете расширить свою сборку, чтобы принять PayloadX и установить там временную метку, в результате чего что-то вроде new PayloadX.Builder(payloadXInstance).setTimestamp(...).build().

+0

Можете ли вы привести пример всех ваших предложений? Это поможет мне лучше понять. На данный момент я смущаюсь, как использовать ваше предложение. – john

+0

@ david Не буду, извините, это превышает количество времени, которое я готов внести. – lexicore