There is also another way to create classes according to the Builder pattern, which corresponds to “Prefers composition over inheritance”.
Define the interface that the parent class Builder inherits:
public interface FactsBuilder<T> { public T calories(int val); }
The implementation of NutritionFacts almost the same (with the exception of the Builder implementation of the FactsBuilder interface):
public class NutritionFacts { private final int calories; public static class Builder implements FactsBuilder<Builder> { private int calories = 0; public Builder() { } @Override public Builder calories(int val) { return this; } public NutritionFacts build() { return new NutritionFacts(this); } } protected NutritionFacts(Builder builder) { calories = builder.calories; } }
Builder child class must extend the same interface (except for another common implementation):
public static class Builder implements FactsBuilder<Builder> { NutritionFacts.Builder baseBuilder; private boolean hasGMO = false; public Builder() { baseBuilder = new NutritionFacts.Builder(); } public Builder GMO(boolean val) { hasGMO = val; return this; } public GMOFacts build() { return new GMOFacts(this); } @Override public Builder calories(int val) { baseBuilder.calories(val); return this; } }
Note that NutritionFacts.Builder is a field inside GMOFacts.Builder (called baseBuilder ). The method implemented from the FactsBuilder interface calls the baseBuilder method with the same name:
@Override public Builder calories(int val) { baseBuilder.calories(val); return this; }
There is also a big change in GMOFacts(Builder builder) . The first constructor call to the parent class constructor should pass the appropriate NutritionFacts.Builder :
protected GMOFacts(Builder builder) { super(builder.baseBuilder); hasGMO = builder.hasGMO; }
Full implementation of the GMOFacts class:
public class GMOFacts extends NutritionFacts { private final boolean hasGMO; public static class Builder implements FactsBuilder<Builder> { NutritionFacts.Builder baseBuilder; private boolean hasGMO = false; public Builder() { } public Builder GMO(boolean val) { hasGMO = val; return this; } public GMOFacts build() { return new GMOFacts(this); } @Override public Builder calories(int val) { baseBuilder.calories(val); return this; } } protected GMOFacts(Builder builder) { super(builder.baseBuilder); hasGMO = builder.hasGMO; } }
R. ZagĂłrski Oct 17 '16 at 13:10 2016-10-17 13:10
source share