Builder Pattern is a creational design pattern that uses simple objects to build a complex object that is independent of objects.
Description
Builder pattern is used when both abstract factory and factory method have some difficulties in using the object with more attributes. To implement the builder pattern, one should create a static class and copy all the content into static class with proper naming conventions.
Builder pattern separates the construction and representation of the object. Decoupling of objects can be done easily.
Advantages
Complex object can be created using simple objects.
Builder pattern is helpful in de-serialization of the complex object.
The construction and representation of the object can be separated easily.
Gain a better control on the construction process.
Internal representation of object can be changed.
Conceptual
figure
Builder class specifies an abstract interface for creating the parts of a Product object.
ConcreteBuilder constructs and puts together all the parts of the product by implementing the Builder interface. It defines and keeps track of the representation that is created and provides an interface for saving the product.
Director class constructs the complex object using the Builder interface.
Product represents the complex object that is being built.
Examples
[java]
public class Device
{
private String HDISK;
private String RAM;
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public String getHDISK()//returns type is String
{
return HDISK;
}
public String getRAM()//return type is string
{
return RAM;
}
public boolean isGraphicsCardEnabled()//return type is boolean
{
return isGraphicsCardEnabled;
}
public boolean isBluetoothEnabled()//return type is boolean
{
return isBluetoothEnabled;
}
private Device(DeviceBuilder builder)
{
this.HDISK=builder.HDISK;
this.RAM=builder.RAM;
this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
this.isBluetoothEnabled=builder.isBluetoothEnabled;
}
public static class DeviceBuilder
{
private String HDISK;
private String RAM;
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public DeviceBuilder(String hdisk, String ram)
{
this.HDISK=hdisk;
this.RAM=ram;
}
public DeviceBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled)
{
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
return this;
}
public DeviceBuilder setBluetoothEnabled(boolean isBluetoothEnabled)
{
this.isBluetoothEnabled = isBluetoothEnabled;
return this;
}
public Device build()
{
return new Device(this);
}
}
}
public class TestBuilderPattern
{
public static void main(String[] args)
{
Device comp = new Device.DeviceBuilder("250 GB", "4 GB").setBluetoothEnabled(true)
.setGraphicsCardEnabled(true).build();
}
}[/java]
In the above example, a static nested class is created and then all the arguments are copied from the outer class to the Builder class and naming convention is followed. If the class name is Device, then the builder class is named as Device Builder.
The Builder class should hold a public constructor with all the required attributes as parameters and methods to set the optional parameters. It should return the same Builder object after setting the optional attribute.
The final step is to provide the build() method in the builder class that will return the Object needed by the client program. For this, a private constructor in the Class with Builder class as argument is required.
Output
Result will be as follows.
[java]
HDisk 250GB
Ram 4GB
[/java]
Summary
Key Points
The problem with large parameters and inconsistent state can be solved and the builder class returns the final object.