Does the Builder Design Pattern Stand the Test of Time?
The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations.
The sample code that usually comes with this pattern is something like this:
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder(); Cook cook = new Cook(); cook.SetPizzaBuilder(hawaiianPizzaBuilder); cook.ConstructPizza(); // create the product Pizza hawaiian = cook.GetPizza();
I find this sort of code to be extremely verbose and hard to read. Especially when we have a lot of options and things to do. Fluent Interfaces, however, are just an instance of the Builder pattern, and they are basically adding a modern API look & feel to the way we are actually constructing objects. Another thing to remember is that we are dealing with C#, and we have things like object initializers to do a lot of the heavy lifting for building objects. You should use that, for most cases.
NHibernate, for example, has the notion of a Builder, using the NHibernate.Cfg.Configuration object. It allows us to put all of the construction / validation code in one spot, and then the actual runtime code in a different place (and can assume a lot about its invariants). It also allows to do a lot of interesting things, like serializing the builder object (to save building time), which is something that you usually can’t / hard to do with real objects.
That said, you should be careful of code like the one listed above .What you have there is an overly abstract system. Requiring multiple steps to just get somewhere. If you find yourself feeding builders into builders, please stop and think about what you are doing. If you got there, you have not simplified the construction process.
Recommendation: This is still a very useful pattern. It should absolutely not be used if all you need to do is just setting some values. Reserve the Builder patterns where you actually have logic and behavior associated with the building process.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Howard Lewis Ship replied on Fri, 2012/11/02 - 12:30pm
I'm a big fan of the builder pattern ... in Java. In most other languages I code in, especially Clojure, this is little or no need for it. Having uniform data types (vectors, maps, sets), a literal syntax for those formats, and (for Clojure) efficient immutable data types means that the language itself acts like the builder pattern.
Jeremy Unruh replied on Sat, 2012/11/03 - 1:30am
Without Builder:
With Builder:
Fabian Kessler replied on Sat, 2012/11/03 - 11:39pm
I completely agree with previous commenters. You don't have to give up on the fluent interface ... just move it to the builder! Today's programming is all about making objects immutable wherever possible. And the builder does exactly this. It makes sure only valid objects are created, and keeps the real object's code lean and clean. And the possibility of hiding the real implementation(s) and changing them later on without breaking backward compatibility or refactoring work really is great.