02 July 2016

tl;dr Patterns, 20 Years Later: The Builder pattern has enjoyed some success within the O-O community, particularly among the crowd that sees it as a way to build fluent APIs (APIs which read, more or less, like a natural language, a la English). Builder has a few tricks up its sleeve beyond just fluent APIs, however.


Separate the construction of a complex object from its representation so that the same construction process can create different representations.


The object is made up of a collection of parts. Builder isn't necessary unless there is a non-trivial construction process (meaning not a simple constructor call). In the Gang-of-Four book, they assumed that the Builder would often be building a Composite, but frankly, this is a limited view; it's trivial to imagine a Builder constructing a Facade (such as a compiler whose optimization or code generation steps will vary) or Interpreter.

Create the complex object independent of the parts that make up the object and how they're assembled. In other words, the Builder will be used to construct not just a single object, but a family of objects that work together to achieve some useful purpose, but we don't want the client to have to worry about the details of doing the actual assembly (or what parts are being assembled).

The construction process must allow different representations for the object that's constructed. The complex object's internals (state and behavior) will need to vary according to different circumstances or needs.

The client wants to defer the creation to an intermediary, a Director. This is sometimes waived under certain circumstances, particularly when the desire is to create a Fluent API, enabling easy direct client construction.

The product created should never be used until its construction is complete, but the steps required for construction need to take place incrementally. A constructor is a pass/fail
operation, meaning once the constructor returns, the object should be in a ready state and available for immediate use---or else it should throw an exception (or signal some other kind of failure) and not be available at all.


In the class Gang-of-Four solution, define a Director object that constructs a ConcreteBuilder, and use that to build the Product (the complex object needing to be constructed). Each ConcreteBuilder inherits from the same AbstractBuilder, which provides the uniform interface for building the individual parts, but the ConcreteBuilder defines the exact collection of parts, the order in which they are constructed, and so on.

There's some interesting questions that emerge from the implementation of a Builder:

Additionally, with Builder, a multi-step configuration/construction pass can allow clients to incrementally construct the object without worry about using the object before it is completely ready (so long as the Builder refuses to pass back the product if doing so would leave the product in an incomplete or partially-constructed state).



Builder brings with it several consequences of note.


There are a couple of patterns that frequently end up connected to, or similar to, Builder: