Avijeet and Satyabrata Dash
Intent
Separate the construction of a complex object from its representation so that
the same construction process can create different representations.
In 30 Seconds
In this pattern, the catch is "create a complex object step by
step". For example, creating an ASCII text document from an RTF document.
Here the steps in creating the ASCII document are to parse the RTF document and
then convert that to ASCII text. The first step is 'construction' and second is
'representation'. The construction process is same irrespective of what target
object format is. Thus moving the conversion responsibility to a different
object called ‘Builder’ would let us use the same parsing routine for other
builders to create different objects out of an RTF document. The RTF document
reader (from construction part) is called the ‘Director’.
Structure
Click here for the diagram
Motivation
From the object collaboration angle we have a director, many builders and
products. All the different builders generally inherit from an abstract builder
class, which declares the general functions to be used by the director to let
the builder create the product in parts. The director contains a reference to
the abstract builder class. The client passes the appropriate builder object to
the director. The builder class encapsulates all internal structure of the
product and is assembled. The director is always implemented to the builder
interface and is oblivious of actual implementation in subclass. Moreover, we
have finer control over the construction process as the objects are created in
steps.
Sample Code
/*
The participants in this example are RTFReader (Director), TextConverter
(Builder), ASCIIConverter (ConcreteBuilder), ASCIIText (Product), and a Client. RTFReader constructs an object using the Builder interface. ASCIIConverter
constructs and assembles the parts of the product by implementing Builder
interface. It also provides an interface i.e. getResult() to retrieve the
product. ASCIIText represents the complex object under construction.
*/
//Abstract Builder class
abstract class TextConverter{
abstract void convertCharacter(char c);
abstract void convertParagraph();
}
// Product
class ASCIIText{
public void append(char c){
//Implement the code here
}
}
//Concrete Builder
class ASCIIConverter extends TextConverter{
ASCIIText asciiTextObj;//resulting product
//converts a character to target representation and appends to the resulting object
void convertCharacter(char c){
char asciiChar = new Character(c).charValue();//gets the ascii charcter
asciiTextObj.append(asciiChar);
}
void convertParagraph(){}
ASCIIText getResult(){
return asciiTextObj;
}
}
//This class abstracts the document object
class Document{
static int value;
char token;
public char getNextToken(){
//Get the next token
return token;
}
}
//Director
class RTFReader{
private static final char EOF='0'; //Delimitor for End of File
final char CHAR='c';
final char PARA='p';
char t;
TextConverter builder;
RTFReader(TextConverter obj){
builder=obj;
}
void parseRTF(Document doc){
while ((t=doc.getNextToken())!= EOF){
switch (t){
case CHAR: builder.convertCharacter(t);
case PARA: builder.convertParagraph();
}
}
}
}
//Client
public class Client{
void createASCIIText(Document doc){
ASCIIConverter asciiBuilder = new ASCIIConverter();
RTFReader rtfReader = new RTFReader(asciiBuilder);
rtfReader.parseRTF(doc);
ASCIIText asciiText = asciiBuilder.getResult();
}
public static void main(String args<>){
Client client=new Client();
Document doc=new Document();
client.createASCIIText(doc);
system.out.println("This is an example of Builder Pattern");
}
}
Here the client has information about the builder he wants and the product it
needs. The client can manipulate builder instance and product instance to get
another product. So, that isolates lot of information about the product internal
structure and its creation from the client and director as well.
Complexities simplified
One of the implementation issues here is the assembly and construction
interface in the abstract builder class. As the object is created in parts, here
it's a case of appending the new parts to existing. But at times the new parts
need previously created parts. In that case a bottom-up approach would help. The
parse tree from the director would pass the child nodes to the builder and the
builder would use the child nodes to create the parent nodes.
The abstract builder class may provide default implementation for all the
concrete builder classes. Generally, the resulted products are very different
from each other so having an abstract product class is not required. At times,
the director and builder can be the same class.
Also Known as and Related Patterns
A composite is what the builder often builds. Abstract factory and builder
have some similarities except that builder focuses on building a complex object
step by step and abstract factory focuses on constructing family of objects
either simple or complex.
(The authors are senior developers at MindTree Consulting. They can be
reached at avijeetd@mindtree.com and satyabrata_dash@mindtree.com.
References: Design Patterns, elements of reusable object-oriented software by
Gamma, Helm, Johnson and Design Patterns in Java by James W. Cooper)