在构建器模式中使用抽象类吗?

时间:2016-12-06 08:24:46

标签: java design-patterns fluent builder-pattern

我有两种来自上游的有效负载:它是PayloadAPayloadBPayloadAPayloadB之间有一些共同的字段,因此我使用这些公共字段创建了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类(这必须是抽象类吗?),其中我有PayloadAPayloadB的所有公共字段,所以我必须以某种方式设置这些字段,我不知道如何使用下面的类:

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

  // getters and setters here
}

问题:

  • 现在让我们说如果我们从上游获得PayloadB,那么我希望key类中的Payload字段是typePayloadB的值PayloadA在所有小写的情况下,如果我们从上游得到world,那么我希望密钥为PayloadB
  • 如果我们从上游获得clientId并且设置了partition,那么我希望15PayloadA,如果我们从clientId获得partition上游,如果设置了15,那么我希望langIdpartition,但如果未设置17,那么我希望createTimestamp成为Payload WebElement table = driver.findElement(By.id("ctl00_TxnContentPage_grdLoanDetails")); WebElement tableBody = table.findElement(By.tagName("tbody")); int rowCount = tableBody.findElements(By.tagName("tr")).size();
  • 我想设置class WindowsElement : DependencyObject, INotifyPropertyChanged { public WindowsElement() { } public double Width { get { return (double)GetValue(WidthProperty); } set { SetValue(WidthProperty, value); } } private static void WidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { WindowsElement element = (WindowsElement)o; double width = (double)e.NewValue; CommonDebug.LogLine("WPC", element, o, width); //element.Width = width; element.RaisedPropertyChanged("Width"); } private static void ActualWidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { WindowsElement element = (WindowsElement)o; double width = (double)e.NewValue; CommonDebug.LogLine("AWPC", o, e, width, element.Width); //element.ActualWidth = width; element.RaisedPropertyChanged("ActualWidth"); } public event PropertyChangedEventHandler PropertyChanged; private void RaisedPropertyChanged(string PropertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); } public static readonly DependencyProperty WidthProperty = DependencyProperty.Register( "Width", typeof(double), typeof(WindowsElement), new PropertyMetadata((double)0, WidthPropertyChanged)); public double ActualWidth { get { return (double)GetValue(ActualWidthProperty); } set { SetValue(ActualWidthProperty, value); } } public static readonly DependencyProperty ActualWidthProperty = DependencyProperty.Register( "ActualWidth", typeof(double), typeof(WindowsElement), new PropertyMetadata((double)0, ActualWidthPropertyChanged)); public static void MessWithBindings() { WindowsElement we1 = new WindowsElement(); WindowsElement we2 = new WindowsElement(); var b = new Binding { Source = we2, Path = new PropertyPath("ActualWidth") }; BindingOperations.SetBinding(we1, WindowsElement.WidthProperty, b); we2.ActualWidth = 13; CommonDebug.LogLine(we1, we1.Width, we1.ActualWidth, we2, we2.Width, we2.ActualWidth); } } 以及构建Payload对象后我必须做的事情。所以例如我构建了PayloadA对象,它将被传递给其他类,我需要在PayloadA对象上设置createTimestamp值。不知道该怎么做?我必须克隆一些东西吗?

如何在构建器模式中使用{{1}}类?我将得到两个不同的有效载荷,并且它们中很少有共同点,所以常见的字段我将它们分离出来。

我是否应该在大型构建器模式类中使用其中的所有内容或多个构建器模式扩展某些内容?

1 个答案:

答案 0 :(得分:2)

  • 我不会将builder个实例传递给PayloadX构造函数。将值作为单独的构造函数参数或调用setter传递。
  • 您可以定义Payload.Builder,其中包含PayloadAPayloadB的公共字段。该类将是一个抽象类,声明一个抽象的build方法。
  • PayloadA.BuilderPayloadB.Builder会延长Payload.Builder,实施build方法。
  • 在此build方法中,您可以实现创建所需的任何自定义逻辑,并设置PayloadX的字段。

好像你想让你的类不可变(顺便说一下,小心applicationPayload)。在这种情况下,你无法真正地设置&#34;任何东西。您只能生成新实例。有很多方法可以做到这一点,例如,您可以实现PayloadX withTimestamp(...)方法。或者,您可以将构建扩展为接受PayloadX并在其中设置时间戳,从而产生类似new PayloadX.Builder(payloadXInstance).setTimestamp(...).build()的内容。