Builder Design Pattern

Here is the “usual” implementation of this design pattern.

package pt.joaobrito.builder;

/**
 * This is the main class
 */
public class BuilderExample {

	public static void main(String[] args) {
		Vehicle v1 = new Client(new CarBuilder()).constructVehicle();
		System.out.println(v1);

		Vehicle v2 = new Client(new BikeBuilder()).constructVehicle();
		System.out.println(v2);

		Vehicle v3 = new Client(new CarBuilder()).constructVehicleWithoutWindowsOrSeats();
		System.out.println(v3);

		Vehicle v4 = new Client(new BikeBuilder()).constructVehicleWithoutWindowsOrSeats();
		System.out.println(v4);
	}
}
/**
 * The Client class has the responsability of building the vehicles
 */
class Client {

	private final VehicleBuilder vehicleBuilder;

	public Client(VehicleBuilder vehicleBuilder) {
		this.vehicleBuilder = vehicleBuilder;
	}

	/**
	 * Builds a complete vehicle
	 * @return a vehicle
	 */
	public Vehicle constructVehicle() {
		return vehicleBuilder.buildType().buildSeats().buildWindows().get();
	}

	/**
	 * Builds a vehicle without parts
	 * @return a vehicle
	 */
	public Vehicle constructVehicleWithoutWindowsOrSeats() {
		return vehicleBuilder.buildType().get();
	}
}

/**
 * This class is the abstract builder
 */
abstract class VehicleBuilder {

	protected Vehicle vehicle;

	public VehicleBuilder() {
		this.vehicle = new Vehicle();
	}

	/**
	 * Vehicle get method
	 * @return the vehicle
	 */
	public Vehicle get() {
		return vehicle;
	}

	/**
	 * The 3 following lines are the methods that must be implemented on the concrete builders
	 * @return
	 */
	public abstract VehicleBuilder buildType();
	public abstract VehicleBuilder buildSeats();
	public abstract VehicleBuilder buildWindows();
}

/**
 * This is a concrete builder for Bikes
 */
class BikeBuilder extends VehicleBuilder {

	@Override
	public VehicleBuilder buildType() {
		vehicle.setType("Bike");
		return this;
	}

	@Override
	public VehicleBuilder buildWindows() {
		vehicle.setWindows(0);
		return this;
	}

	@Override
	public VehicleBuilder buildSeats() {
		vehicle.setSeats(2);
		return this;
	}

}

/**
 * This is the concrete builder for Cars
 */
class CarBuilder extends VehicleBuilder {

	@Override
	public VehicleBuilder buildType() {
		vehicle.setType("Car");
		return this;
	}

	@Override
	public VehicleBuilder buildSeats() {
		vehicle.setSeats(5);
		return this;
	}

	@Override
	public VehicleBuilder buildWindows() {
		vehicle.setWindows(4);
		return this;
	}


}

/**
 * This is the vehicle class
 */
class Vehicle {

	private String type;
	private int seats;
	private int windows;

	public void setType(String type) {
		this.type = type;
	}

	public void setSeats(int seats) {
		this.seats = seats;
	}

	public void setWindows(int windows) {
		this.windows = windows;
	}
	
	/**
	 * @return a printable vehicle
	 */
	@Override
	public String toString() {
		return "Vehicle[Type: " + type + "; Seats: " + seats + "; Windows: " + windows + "]";
	}

}

 

The result is:
builder2

UML
builder2_uml

 

 

Builder Design Pattern (simple way)

This design pattern allows us to create an object with the advantage that the same construction process can create different representations of that object. Here is the simplest implementation of this design pattern.

In a next tutorial we will explain the other way of doing the same thing, with more flexibility but with a more complex implementation.

So, let’s start creating a car!

package pt.joaobrito.builder;

/**
 * This is the class that we will create object of
 */
class Car {

	private String brand, model, version;

	/**
	 * This private constructor avoids the user to create the object in the complex way
	 * using the new keyword.
	 */
	private Car() {}

	/**
	 * This method allows us to get the builder of the car without instantiating the car
	 * 
	 * @return the builder instance
	 */
	public static Builder getBuilder() { return new Builder(); }

	public String getBrand() { return this.brand; }

	public String getModel() { return this.model; }

	public String getVersion() { return this.version; }

	/**
	 * This is the printable version of the car
	 * @return a printable car
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("Your new car -> ");
		if (brand != null) { sb.append("brand: " + brand); }
		if (model != null) { sb.append(", model: " + model); }
		if (version != null) { sb.append(", version: " + version); }
		return sb.toString();
	}

	/**
	 * This class is the builder itself.
	 * Notice that in every builder method we always return the builder instance. 
	 * This allows us to continue building more parts of the car in one single line.
	 */
	static final class Builder {

		/**
		 * Here we keep an instance of the car we are building. When finished we return it.
		 */
		private final Car car = new Car();

		/**
		 * This is the method that return the car we previously built (or not)
		 * @return
		 */
		public Car getInstance() { return car.getBrand() == null ? null : car; }

		public Builder buildBrand(String brand) {
			this.car.brand = brand;
			return this;
		}

		public Builder buildModel(String model) {
			this.car.model = model;
			return this;
		}

		public Builder buildVersion(String version) {
			this.car.version = version;
			return this;
		}
	}

}

public class Builder {

	public static void main(String[] args) {
		Car c1 = Car.getBuilder().buildBrand("BMW").buildModel("Serie 5").buildVersion("535d Touring").getInstance();
		Car c2 = Car.getBuilder().buildBrand("VW").buildModel("Passat").getInstance();
		Car c3 = Car.getBuilder().buildModel("Class E").getInstance();
		
		System.out.println(c1);
		System.out.println(c2);
		System.out.println(c3 == null ? "You don't have a car! Please create a car with a brand defined." : c3);
	}
}

 

The final result:

builder

Singleton Design Pattern

With his design patttern we allways get the same instance, as you can see next.

  1. The Singleton class:
package pt.joaobrito.singleton;

public final class Singleton {

	/**
	 * A private constructor. This is necessary in order to not allow create a new Singleton object
	 * from the outside with the keyword new
	 */
	private Singleton() {}

	private static final class SingletonHolder {
		public static final Singleton INSTANCE = new Singleton();
	}

	public static final Singleton getInstance() {
		return SingletonHolder.INSTANCE;
	}
}

 

2. The main class:

package pt.joaobrito.singleton;

public class Main {

	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();

		// test if the reference are the same
		System.out.println(s1 == s2);
	}

}

 

3. The result:

singleton

 

UML
singleton