Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.
For example, let’s think about how to create a House
object. To build a simple house, you need to construct four walls
and a floor, install a door, fit a pair of windows, and build a roof. But
what if you want a bigger, brighter house, with a backyard and other
goodies (like a heating system, plumbing, and electrical wiring)?
The simplest solution is to extend the base House
class and create a set of subclasses to cover all combinations of
the parameters. But eventually you’ll end up with a considerable number of
subclasses. Any new parameter, such as the porch style, will require
growing this hierarchy even more.
There’s another approach that doesn’t involve breeding subclasses. You
can create a giant constructor right in the base House
class with all possible parameters that control the house object.
While this approach indeed eliminates the need for subclasses, it creates
another problem.
The pattern organizes object construction into a set of steps (buildWalls
, buildDoor
, etc.). To create an object, you execute a series of these steps on
a builder object. The important part is that you don’t need to call all of
the steps. You can call only those steps that are necessary for producing
a particular configuration of an object.
Some of the construction steps might require different implementation when you need to build various representations of the product. For example, walls of a cabin may be built of wood, but the castle walls must be built with stone.
In this case, you can create several different builder classes that implement the same set of building steps, but in a different manner. Then you can use these builders in the construction process (i.e., an ordered set of calls to the building steps) to produce different kinds of objects.
For example, imagine a builder that builds everything from wood and glass, a second one that builds everything with stone and iron and a third one that uses gold and diamonds.
By calling the same set of steps, you get a regular house from the first builder, a small castle from the second and a palace from the third.
However, this would only work if the client code that calls the building steps is able to interact with builders using a common interface.
Structure
public class Computer { //required parameters private String HDD; private String RAM; //optional parameters private boolean isGraphicsCardEnabled; private boolean isBluetoothEnabled; public String getHDD() { return HDD; } public String getRAM() { return RAM; } public boolean isGraphicsCardEnabled() { return isGraphicsCardEnabled; } public boolean isBluetoothEnabled() { return isBluetoothEnabled; } private Computer(ComputerBuilder builder) { this.HDD=builder.HDD; this.RAM=builder.RAM; this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled; this.isBluetoothEnabled=builder.isBluetoothEnabled; } //Builder Class public static class ComputerBuilder{ // required parameters private String HDD; private String RAM; // optional parameters private boolean isGraphicsCardEnabled; private boolean isBluetoothEnabled; public ComputerBuilder(String hdd, String ram){ this.HDD=hdd; this.RAM=ram; } public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) { this.isGraphicsCardEnabled = isGraphicsCardEnabled; return this; } public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) { this.isBluetoothEnabled = isBluetoothEnabled; return this; } public Computer build(){ return new Computer(this); } } }
Notice that Computer class has only getter methods and no public constructor. So the only way to get a Computer object is through the ComputerBuilder class.
Here is a builder pattern example test program showing how to use Builder class to get the object.
public class TestBuilderPattern { public static void main(String[] args) { //Using builder to get the object in a single line of code and //without any inconsistent state or arguments management issues Computer comp = new Computer.ComputerBuilder( "500 GB", "2 GB").setBluetoothEnabled(true) .setGraphicsCardEnabled(true).build(); } }