The classic Builder Pattern requires fields to be declared in the class-to-be-built and the exact same fields to be declared in the builder class. This can lead to problems when there are many fields and, during refactoring, the field types are not kept in sync. Here's an example of what I mean (I borrowed this code sample from an article by Joshua Block):
// Builder Pattern
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
private int servingSize = 0;
private int servings = 0;
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder servingSize(int val)
{ servingSize = val; return this; }
public Builder servings(int val)
{ servings = val; return this; }
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
Now let's assume that servingSize
needs to be changed from int
to long
and that this change is done in NutritonFacts
but, by accident, not also done in the static Builder
.
Admittedly less problematic is the number of fields. NutritionFacts
has 6 fields and, therefore, so does Builder
. What if there were 20 or 100 fields? Duplicating them all in NutritionFacts
and Builder
would be real pain. Is there a better way so that all the duplication and potential for type-syncing errors can be avoided?