Builder patterns are cool. When I saw Joshua Bloch's in Effective Java
2 I just couldn't help wanting slightly more. So I created another one
that is simpler and more secure to use. It is slightly more complex to
write though.

The Effective Java builder pattern:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories
(100).sodium(35).carbohydrate(27).build();

The problem is that the required fields are not documented in that
code.
Also, the "new ButritionFacts.Builder" notion will make a lot of Java
developers trip.

Instead, how about:

NutritionFacts cocaCola = NutritionFacts.servingSize(240).servings
(8).calories(100).sodium(35).carbohydrate(27).build();


What is good about it is that it is extremely easy to read. It scales
with both the numbers of required fields AND optional fields. And it
is completely type safe.
And, you can absolutely never go wrong. In every stage of the required
args there is only one valid method to call. It works very well with
code completion...

The only downside is that the implementation is slightly more complex
for the required parameters.

If the notion doesn't look enough like a creation of an object a
simple variation with all the benefits can look like:

NutritionFacts cocaCola = new NutritionFacts.Builder().servingSize
(240).servings(8).calories(100).sodium(35).carbohydrate(27).build();

The best would be if an IDE plugin could spit out the code
automatically after a "Build Builder class..." command.

Hope someone finds this useful.

Cheers,
Mikael Grev

public final class NutritionFacts
{
    // Required
    private final int servingSize, servings;

    // Optional
    private final int calories, fat, sodium, carbohydrate;

    private NutritionFacts(Builder builder)
    {
        servingSize   = builder.servingSize;
        servings      = builder.servings;
        calories      = builder.calories;
        fat           = builder.fat;
        sodium        = builder.sodium;
        carbohydrate  = builder.carbohydrate;
    }

    public static ServingsArg servingSize(int servingSize)
    {
        return new ServingsArg(servingSize);
    }

    public final static class ServingsArg
    {
        private final int servingSize;

        private ServingsArg(int servingSize)
        {
            this.servingSize = servingSize;
        }

        public Builder servings(int servings)
        {
            return new Builder(servingSize, servings);
        }
    }

    public final static class Builder
    {
        // Required
        private final int servingSize;
        private final int servings;

        // Optional
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbohydrate = 0;

        private Builder(int servingSize, int servings)
        {
            this.servingSize = servingSize;
            this.servings    = servings;
        }

        public NutritionFacts build()
        {
            return new NutritionFacts(this);
        }

        public Builder calories(int i)
            {this.calories = i; return this; }
        public Builder fat(int i)
            {this.fat = i; return this; }
        public Builder sodium(int i)
            {this.sodium = i; return this; }
        public Builder carbohydrate(int i)
            {this.carbohydrate = i; return this; }
   }
}

--

You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=.


Reply via email to