A key to the understanding of the GoF design patterns is their intent. For the builder it is:
Separate the construction of a complex object from its representation
so that the same construction process can create different
representations
Simplified variant
When looking at the solution proposed by GoF, what strikes most is the separate building and assembly of parts: the structure distinguishes the Director
and the Builder
and enables a step by step construction:
- This aspect of the pattern apparently stroke Joshua Bloch as well, because his approach uses this separation to set a lot of optional parameters.
- This sequence of events also allows for validating parts before assembling the result, as you've notice in this XmlBuilder.
While being very useful, I think however that these examples focus only on one aspect of the pattern and miss the real intent. Thus their structure appears simplified by merging either Director
and Builder
or Builder
and ConcreteBuilder
.
The missing intent
For GoF, it's not only about the separation between Director
and Builder
to build by step, but also the separation between Builder
and ConcreteBuilded
:
- If you look well at pattern structure, you'll notice that the
Builder
provides the polymorphic/virtual buildPart()
methods. But getResult()
to obtain the final product is a method of ConcreteBuilder
that is not included in the abstract Builder
's interface. So it can use different parameters or return different types.
- The GoF sequence diagram on page 99 shows furthermore that a
Client
calls the Director
for constructing the object and trigger the building of parts (perhaps using temporary objects), but that it's up to the client to call getResult()
directly from ConcreteBuilder.
- In fact, the client knows the ConcreteBuilder (may be even it instantiates it) and calls the
Director
by referfencing it.
This makes clear that this pattern is not so for building the parts and assemble the whole (which after all is nothing more than a helper to simplify providing all the elements at once), but more for returning very different "representations" (classes) using the same procedure for constructing the parts.
Real life use of the complete pattern
The typical use in real life is to build composite objects having different types of implementation/representation, such as for example different graphical representations/views (e.g. Entity/Relationship or UML model), different input or output formats (e.g. JSON or XML document) or encodings (e.g ASCII vs UTF16/32).
A concrete use could for example be ADO.net with DbCommandBuilder
that is implemented by concrete SqlCommandBuilder
, OracleCommandBuilder
, ODBCCommandBuilder
to generate db specific commands.