0

I am wondering when should I use builder with static class inside and where classical one?

Implementation from Effective Java book

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;
  }
}

Regular implementation

(just diagram) enter image description here

4

2 回答 2

2

在以下情况下,您应该考虑使用 Builder 模式 1.您需要防止对象进入不一致的状态,并且 2.使用构造函数参数将难以使用/读取,因为您需要使用大量(大量)属性放。

使用普通的默认构造函数 + getter/setter 可能会让消费者进入无效/不一致的状态。IE 他们可能会忘记设置一个非常重要的属性(例如 Cheese),但他们不会被阻止这样做,并且无论如何都可以创建 Pizza,即使处于“坏”状态。消费者有责任在构造后适当地设置对象的状态。

您通常可以通过构造函数参数来防止这种情况。例如

private Pizza() {}
public Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) 
{
    ...
}

但是当您有大量参数时,这可能很难读/写。

所以,总而言之,当你想保证你的对象不能在不一致的状态下构造并且你有太多的字段需要设置,使用构造函数参数会使其难以使用和阅读时,你可以考虑使用 Builder 模式.

于 2013-09-13T04:33:52.293 回答
1

我想说,当您准备加倍努力使类构造函数看起来很自然时

谁能否认这读起来像好代码

Pizza pizza = new Pizza.Builder(10).cheese(true).peperoni(true).bacon(true).build();

我的意思是……那不是很甜吗?它甚至有培根

第二个(也是更常见的)选项是:

Pizza pizza = new Pizza(10);
pizza.setCheese(true);
pizza.setPeperoni(true);
pizza.setBacon(true);

这将更容易使用反射,因此更容易序列化/反序列化 - 但会受到更繁琐和冗长的构造的影响。

第三个也是最不灵活的是:

Pizza pizza = new Pizza(10, true, true, true);

但是可以同时提供第 2 和第 3 机制,这可能是一个加号。

如何选择

没有简单的选择方法。如果您想吸引您的客户购买您的库,您可以提供所有三种方法,但这会破坏使用 Builder 的主要好处之一(它隐藏了实际的构造函数)。

我建议使用第二种方法,也许是第三种方法,除非有充分的理由采用不寻常的方式使用 Builder。

于 2013-09-09T22:34:16.817 回答