我想知道何时应该使用内部静态类的构建器和经典类的构建器吗?
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;
}
}
(只是图表)
答案 0 :(得分: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);
但是可以同时提供第二和第三种机制,这可以是一个加号。
如何选择
没有简单的选择方法。如果您想吸引客户购买您的库,您可以提供所有三种方法,但这会破坏使用Builder(隐藏实际构造函数)的主要好处之一。
我建议使用第二种方法,也许第三种方法,除非有充分的理由采用不同寻常的使用Builder的方法。
答案 1 :(得分:1)
您应该考虑在 1时使用Builder模式。您需要防止对象进入不一致状态 AND 2。使用构造函数参数将难以使用/读取,因为您需要设置一些笨重(大量)的属性。
使用普通的默认构造函数+ getter / setter可能允许使用者进入无效/不一致状态。 I.E.他们可能忘记设置一个非常重要的属性(如奶酪),但他们不能这样做,并且无论如何都可以创建一个披萨,即使是在一个"坏"州。消费者负担在施工后适当地设置对象的状态。
您通常可以通过构造函数参数来阻止此操作。 E.G。
private Pizza() {}
public Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon)
{
...
}
但是当你有大量参数时,这可能很难读/写。
因此,总而言之,当您想要保证您的对象不能构建在一个不一致的状态时,您有太多的字段要设置,使用构造函数参数会使其难以使用和读取,您可以考虑使用Builder模式。