Setter and (不是 OR 或 VS ) 生成器模式

2022-09-04 07:11:20

我有一种情况,我使用生成器模式来构造对象。最好的例子是披萨代码

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

目前为止,一切都好。

现在让我们假设一个用例,我需要.这需要一个.我从未见过构建器模式与 setter 共存的单一示例,这让我怀疑我所做的是一种反模式。updatecheesesetter

二传手和建造者可以共存吗?


答案 1

您从未见过使用过,因为大多数时候,生成器模式用于构建不可变对象。

但我不明白为什么他们不能共存。构建器生成一个对象,并且您希望生成的对象是可变的,然后它可以具有 setter。但是,如果它是可变的并且具有 setter,为什么不使用简单的构造函数来构建对象,并调用 setter 来更改状态呢?构建器不再真正有用,除非许多字段中只有一两个字段是可变的。


答案 2

现在让我们假设一个用例,我需要.这需要一个.updatecheesesetter

与其考虑 setter 或构建者,不如尝试考虑一个类的责任以及提供给该类用户的服务。

您在这里所说的 setter 只是一个转换对象的服务。构建器是创建复杂对象的服务。

如果您要提供访问属性的 setter(或应该对客户端保密的复杂对象的详细信息),则违反了封装。这是一种反模式。你的奶酪例子不足以揭示为什么这可能是坏的。用户是否需要知道比萨饼有奶酪并能够对其进行修改?

正如JB Nizet所说,没有理由两种服务都不存在,但我会问一个问题,揭示细节是否好。


推荐