Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在生成器模式中使用抽象类?_Java_Design Patterns_Fluent_Builder Pattern - Fatal编程技术网

Java 在生成器模式中使用抽象类?

Java 在生成器模式中使用抽象类?,java,design-patterns,fluent,builder-pattern,Java,Design Patterns,Fluent,Builder Pattern,我有两种来自上游的有效载荷:要么是PayloadA要么是PayloadB。在PayloadA和PayloadB之间有一些公共字段,所以我用这些公共字段创建了PayloadA类,其余的我为每个有效负载创建了两个构建器类 下面是PayloadA的生成器类: public final class PayloadA { private final String clientId; private final String langid; private final String device

我有两种来自上游的有效载荷:要么是
PayloadA
要么是
PayloadB
。在
PayloadA
PayloadB
之间有一些公共字段,所以我用这些公共字段创建了
PayloadA
类,其余的我为每个有效负载创建了两个构建器类

下面是
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
}
现在我创建了另一个类,它是
Payload
class(这必须是抽象类吗?),其中我有
PayloadA
PayloadB
的所有公共字段,因此我必须以某种方式设置这些字段,我不确定如何使用下面的类:

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

  // getters and setters here
}
问题:

  • 现在让我们假设如果我们从上游获得
    PayloadB
    ,那么我希望
    PayloadB
    类中的
    key
    字段是
    PayloadB
    类中所有小写形式的
    type
    的值,如果我们从上游获得
    PayloadA
    ,那么我希望key是
    world
  • 而且如果我们从上游获得
    PayloadB
    ,如果设置了
    clientId
    ,然后我希望
    partition
    成为
    15
    如果我们从上游获得
    PayloadA
    并且如果
    clientId
    被设置,那么我希望
    partition
    成为
    15
    ,但是如果没有设置并且
    langId
    在那里,那么我希望
    partition
    成为
    17
  • 我想设置
    createTimestamp
    ,这也是我在构建有效负载对象之后必须做的。例如,我构建了PayloadA对象,它将被传递给其他类,在那里我需要在PayloadA对象上设置CreateTimstamp值。不知道该怎么做?我必须克隆一些东西吗
如何在构建器模式中使用
有效负载
类?我将得到两个不同的有效载荷,它们中几乎没有共同点,所以我在一个抽象类中将它们分离出来

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

  • 我不会将
    builder
    实例传递给
    PayloadX
    构造函数。将值作为单个构造函数参数或调用设置器传递
  • 您可以定义
    Payload.Builder
    ,它将保存
    PayloadA
    PayloadB
    的公共字段。这个类将是一个抽象类,它声明了一个抽象的
    build
    方法
  • PayloadA.Builder
    PayloadB.Builder
    将扩展
    PayloadA.Builder
    ,实现
    build
    方法
  • 在这个
    build
    方法中,您可以实现创建和设置
    PayloadX
    字段所需的任何自定义逻辑
看起来您希望使类不可变(顺便提一下,小心
applicationPayload
)。在这种情况下,您无法真正“设置”任何内容。您只能生成一个新实例。有很多方法可以做到这一点,例如,您可以实现
PayloadX with timestamp(…)
方法。或者,您可以扩展构建以接受
PayloadX
并在那里设置时间戳,从而生成类似于
new PayloadX.Builder(payloadXInstance).setTimestamp(…).build()

  • 我不会将
    builder
    实例传递给
    PayloadX
    构造函数。将值作为单个构造函数参数或调用设置器传递
  • 您可以定义
    Payload.Builder
    ,它将保存
    PayloadA
    PayloadB
    的公共字段。这个类将是一个抽象类,它声明了一个抽象的
    build
    方法
  • PayloadA.Builder
    PayloadB.Builder
    将扩展
    PayloadA.Builder
    ,实现
    build
    方法
  • 在这个
    build
    方法中,您可以实现创建和设置
    PayloadX
    字段所需的任何自定义逻辑

看起来您希望使类不可变(顺便提一下,小心
applicationPayload
)。在这种情况下,您无法真正“设置”任何内容。您只能生成一个新实例。有很多方法可以做到这一点,例如,您可以实现
PayloadX with timestamp(…)
方法。或者您可以扩展您的构建以接受
PayloadX
并在那里设置时间戳,从而生成类似
new PayloadX.Builder(payloadXInstance).setTimestamp(…).build()

您能提供一个上述所有建议的示例吗?这将帮助我更好地理解。到目前为止,我对如何使用你的建议感到困惑。@david对不起,这不会超过我准备贡献的时间。你能举一个例子说明你所有的建议吗?这将帮助我更好地理解。到目前为止,我对如何使用您的建议感到困惑。@david我不会,对不起,这超过了我准备贡献的时间。首先,您为什么要使用构建器?看起来代码设计过度了…一般来说,所有这些有效负载都有很多字段。为了使示例更易于理解,我这样做了。好吧,你们之所以引入构建器,是因为有大量的类。您是否已经考虑过在较小的类中进行重构,从而解决问题的根源?目前,你的问题听起来像是一个问题:你问如何在构建器中使用抽象类(这是一个非常罕见的问题),而不是问自己“为什么我最终会出现这样一个奇怪的构造?”嗯,那么我应该如何解决这个问题?你需要
PayloadX
?他们是DTO还是BO?它们是否真的包含一些业务逻辑,或者只是一堆getter?发布完整的代码(至少所有的属性)现实吗?首先,为什么要使用构建器?看起来代码设计过度了…一般来说
public abstract class Payload {
  private long createTimestamp;
  private String partition;
  private String key;
  // some other fields here

  // getters and setters here
}