0

I have recently read Effective Java and I found that the Builder Pattern (item #2) is very interesting. However, I have a question: why should we create a static builder when we could do this:

 // 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);

When doing this, we could avoid creating 2 instances.

Could you please explain what the problems are with this method?

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
nguyentt
  • 649
  • 6
  • 13
  • 2
    One other point: the builder pattern is frequently misused in projects. You shouldn't use a builder pattern if all you're doing is simply calling every setter every time anyway. It's only useful when there are multiple ways to construct an object, maybe with optional parts, and you want to make sure it is constructed in a valid way. The number of times I've seen people write a pointless builder for every POJO... :( – David Lavender Jul 19 '17 at 10:24
  • 1
    @MrSpoon that's not true - it's perfectly reasonable to have a builder that you expect callers to invoke every method on *if it aids usability or readability*. For instance a constructor that takes several parameters of the same type is easy to misuse, whereas a builder pattern makes every parameter explicit. EJ Item 2 discusses exactly this. – dimo414 Nov 22 '17 at 10:26
  • Joshua says "many OPTIONAL parameters". When you create an object via its builder with 10 setter calls, you are required to jump back and forth between the call/declaration sites - no auto-complete/hints from IDE. Usability is questionable. When you review code others' code in PRs, you have to open the builder definition, and verify manually if everything required was invoked. Readability doesn't help here. Joshua's builder solves the combinatorial explosion of optional parameters, but the number/primitiveness of parameters is still indicative of possibly missing abstractions. – iwat0qs Jan 07 '22 at 16:53

2 Answers2

3

A Builder allows to abstract the construction process.

Just assume you want to have your NutritionFacts an immutable class. In this case the Builder could provide all the setters and finally call a private constructor that takes all of them (the ones not set are filled with reasonable defaults), while the class itself does not provide any setters.

Another point is that you might want to do some validation on the values set, especially relations between values. A builder pattern will always contain a build() method where you can do this.

In the example you provided it is indeed equivalent to have the setter methods in the Builder or in the class itself.

Izruo
  • 2,246
  • 1
  • 11
  • 23
2

At each step you have an incomplete object. Builder can validate the object and this way you are protecting people from misusing your class.

diginoise
  • 7,352
  • 2
  • 31
  • 39