在有效的Java中删除生成器模式的生成器类

在有效的Java中删除生成器模式的生成器类,java,builder-pattern,effective-java,Java,Builder Pattern,Effective Java,我最近阅读了有效的Java,发现构建器模式(第2项)非常有趣。 但是,我有一个问题:既然我们可以这样做,为什么我们要创建一个静态构建器: // JavaBeans Pattern public class NutritionFacts { private int servingSize; private int servings; private int calories; private int fat; public NutritionFacts() { } public Nutr

我最近阅读了有效的Java,发现构建器模式(第2项)非常有趣。 但是,我有一个问题:既然我们可以这样做,为什么我们要创建一个静态构建器:

 // JavaBeans Pattern 
public class NutritionFacts {

private int servingSize;
private int servings;
private int calories;
private int fat;

public NutritionFacts() {
}

public NutritionFacts servingSize(int val) {
    this.servingSize = val;
    return this;
}

public NutritionFacts servings(int val) {
    this.servings = val;
    return this;
}

public NutritionFacts calories(int val) {
    this.calories = val;
    return this;
}

public NutritionFacts fat(int val) {
    this.fat = val;
    return this;
}

}

//usage
NutritionFacts nf = new NutritionFacts().servingSize(5).servings(4).calories(3).fat(1);
这样做时,我们可以避免创建两个实例


你能解释一下这种方法有什么问题吗?

A
Builder
允许抽象施工过程

只要假设您想让您的
NutritionFacts
成为一个不可变的类。在这种情况下,
Builder
可以提供所有setter,并最终调用一个私有构造函数,该构造函数接受所有setter(未设置的构造函数使用合理的默认值填充),而类本身不提供任何setter

另一点是,您可能希望对值集进行一些验证,尤其是值之间的关系。构建器模式将始终包含一个
build()
方法,您可以在其中执行此操作


在您提供的示例中,实际上相当于在
Builder
或类本身中使用setter方法。

A
Builder
允许抽象构造过程

只要假设您想让您的
NutritionFacts
成为一个不可变的类。在这种情况下,
Builder
可以提供所有setter,并最终调用一个私有构造函数,该构造函数接受所有setter(未设置的构造函数使用合理的默认值填充),而类本身不提供任何setter

另一点是,您可能希望对值集进行一些验证,尤其是值之间的关系。构建器模式将始终包含一个
build()
方法,您可以在其中执行此操作


在您提供的示例中,实际上相当于将setter方法放在
Builder
或类本身中。

每个步骤都有一个不完整的对象。生成器可以验证对象,这样可以防止人们误用您的类。

在每个步骤中,您都有一个不完整的对象。生成器可以验证对象,这样可以防止人们误用类。

还有一点:生成器模式在项目中经常被误用。如果您所做的只是每次调用每个setter,那么就不应该使用builder模式。只有当有多种方法来构造对象(可能有可选的部分)并且您希望确保以有效的方式构造对象时,它才有用。我见过很多次人们为每个POJO编写一个毫无意义的生成器…:(@MrSpoon这不是真的-如果有助于可用性或可读性,那么有一个构建器,您希望调用方调用其上的每个方法是完全合理的。例如,一个获取多个相同类型参数的构造函数很容易被误用,而一个构建器模式使每个参数都显式。EJ第2项正好讨论了这一点。一个她的观点:builder模式在项目中经常被误用。如果您所做的只是每次调用每个setter,那么就不应该使用builder模式。它只有在有多种方法构造对象时才有用,可能有可选的部分,并且您希望确保它以有效的方式构造。时间数我看到人们为每个POJO编写了一个毫无意义的生成器…:(@MrSpoon这不是真的-如果有助于可用性或可读性,那么有一个构建器,您希望调用方调用其上的每个方法是完全合理的。例如,一个获取多个相同类型参数的构造函数很容易被误用,而一个构建器模式使每个参数都显式。EJ第2项正好讨论了这一点。