Sure Reinier, copy it to where ever you want. It's in the Public
Domain from now. Mentioning the source is nice though. :)

It was a year ago that I wrote that code for a mail conversation with
Josh Bloch. I haven't thought about it until another thread brought up
the builder pattern.

Your points are valid, there's more to do. But we would need an IDE
plugin for it and I don't have the time to write one. But maybe
someone else do? That was my thought at least.

Cheers,
Mikael

On Nov 21, 5:36 pm, Reinier Zwitserloot <[email protected]> wrote:
> Looks interesting. Some comments:
>
> 1. Wouldn't it be technically nicer to let the builder contain the
> code mapping builder properties onto the constructor? So, have a
> constructor listing all the fields (optional and required), which just
> assigns them to the (probably final) fields. I guess this is code
> duplication, but clearly you need either an IDE plugin, a command line
> tool, or something like Project Lombok to actually write all this code
> for you; it's ludicrous to do it by hand. Thus, verbosity is
> irrelevant.
>
> 2. One of the advantages of a builder is that you can use them as a
> StringBuilder-esque device; something to pass around between different
> methods if a batch of them are each responsible for only building a
> part of the whole NutritionFacts object. However, by forcing the
> ordering, you sort of ruin the ability to do this at least for the
> required parameters. A fix that works as well with the type system as
> this concept of yours seems impossible without at least something like
> Michael Ernst's Checking Framework (and a custom plugin for it), but
> you can alleviate the problem by including setters for the required
> fields in the final builder returned. That way, the method that starts
> the build process is forced to pick defaults, but later methods can
> override them.
>
> This seems like an excellent idea for a lombok plugin. May I copy your
> post to the lombok newsgroup?
>
> On Nov 21, 4:24 pm, mikaelgrev <[email protected]> wrote:
>
> > 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