Skip to content

Latest commit

 

History

History
211 lines (164 loc) · 7.68 KB

builder_pattern.md

File metadata and controls

211 lines (164 loc) · 7.68 KB

Certainly! The Builder pattern is used to construct a complex object step by step. It separates the construction of an object from its representation, allowing you to create different types and representations of the object using the same construction process.

When to Use the Builder Pattern:

  • When an object is too complex to be created in a single step (e.g., it requires multiple steps or configurations).
  • When you want to make the construction process independent of the components that make up the object.
  • When you want different representations of the same construction process (e.g., building a house with different materials).

Key Components of the Builder Pattern:

  1. Builder: Interface or abstract class that defines the building steps for creating an object.
  2. Concrete Builder: Implements the Builder interface and provides specific implementations for building steps.
  3. Director: Controls the building process by using the builder object.
  4. Product: The complex object that is being built.

Example: Building a House

Let's say we are building a House object, and the house can have a different number of rooms, doors, windows, etc. The Builder pattern allows us to construct houses in a step-by-step manner and customize them as needed.

1. Product Class (House)

// The Product class that we want to build
class House {
    private int rooms;
    private int doors;
    private int windows;
    private boolean hasGarage;
    private boolean hasSwimmingPool;

    // Setters for each attribute
    public void setRooms(int rooms) {
        this.rooms = rooms;
    }

    public void setDoors(int doors) {
        this.doors = doors;
    }

    public void setWindows(int windows) {
        this.windows = windows;
    }

    public void setHasGarage(boolean hasGarage) {
        this.hasGarage = hasGarage;
    }

    public void setHasSwimmingPool(boolean hasSwimmingPool) {
        this.hasSwimmingPool = hasSwimmingPool;
    }

    public String getHouseDetails() {
        return "House with " + rooms + " rooms, " + doors + " doors, " + windows + " windows, " +
               (hasGarage ? "a garage" : "no garage") + ", and " +
               (hasSwimmingPool ? "a swimming pool" : "no swimming pool");
    }
}

2. Builder Interface

The Builder interface defines the steps required to build a House. These methods return the builder itself (for method chaining) and allow for flexible construction.

// Builder Interface
interface HouseBuilder {
    HouseBuilder buildRooms(int numberOfRooms);
    HouseBuilder buildDoors(int numberOfDoors);
    HouseBuilder buildWindows(int numberOfWindows);
    HouseBuilder buildGarage(boolean hasGarage);
    HouseBuilder buildSwimmingPool(boolean hasSwimmingPool);
    House getHouse();  // Return the final house product
}

3. Concrete Builder

The Concrete Builder implements the steps defined in the builder interface to build a specific type of house.

// Concrete Builder implementation
class ConcreteHouseBuilder implements HouseBuilder {
    private House house;

    public ConcreteHouseBuilder() {
        this.house = new House();  // Start with an empty house
    }

    @Override
    public HouseBuilder buildRooms(int numberOfRooms) {
        house.setRooms(numberOfRooms);
        return this;
    }

    @Override
    public HouseBuilder buildDoors(int numberOfDoors) {
        house.setDoors(numberOfDoors);
        return this;
    }

    @Override
    public HouseBuilder buildWindows(int numberOfWindows) {
        house.setWindows(numberOfWindows);
        return this;
    }

    @Override
    public HouseBuilder buildGarage(boolean hasGarage) {
        house.setHasGarage(hasGarage);
        return this;
    }

    @Override
    public HouseBuilder buildSwimmingPool(boolean hasSwimmingPool) {
        house.setHasSwimmingPool(hasSwimmingPool);
        return this;
    }

    @Override
    public House getHouse() {
        return this.house;
    }
}

4. Director Class

The Director class defines the sequence of building steps and uses the builder to create a house. The client can pass different builders to the director to get various types of houses.

// Director class responsible for constructing the house
class HouseDirector {
    private HouseBuilder builder;

    public HouseDirector(HouseBuilder builder) {
        this.builder = builder;
    }

    // Construct a basic house
    public House constructBasicHouse() {
        return builder.buildRooms(2)
                      .buildDoors(1)
                      .buildWindows(4)
                      .buildGarage(false)
                      .buildSwimmingPool(false)
                      .getHouse();
    }

    // Construct a luxury house
    public House constructLuxuryHouse() {
        return builder.buildRooms(5)
                      .buildDoors(3)
                      .buildWindows(10)
                      .buildGarage(true)
                      .buildSwimmingPool(true)
                      .getHouse();
    }
}

5. Client Code

The client creates a ConcreteHouseBuilder, passes it to the HouseDirector, and uses the director to construct the house. The builder can create different types of houses using the same construction process.

public class Main {
    public static void main(String[] args) {
        // Create a builder
        HouseBuilder builder = new ConcreteHouseBuilder();
        
        // Create a director that will manage the construction process
        HouseDirector director = new HouseDirector(builder);

        // Build a basic house
        House basicHouse = director.constructBasicHouse();
        System.out.println(basicHouse.getHouseDetails());  // Output: House with 2 rooms, 1 doors, 4 windows, no garage, and no swimming pool

        // Build a luxury house
        House luxuryHouse = director.constructLuxuryHouse();
        System.out.println(luxuryHouse.getHouseDetails());  // Output: House with 5 rooms, 3 doors, 10 windows, a garage, and a swimming pool
    }
}

Output:

House with 2 rooms, 1 doors, 4 windows, no garage, and no swimming pool
House with 5 rooms, 3 doors, 10 windows, a garage, and a swimming pool

Explanation of the Builder Pattern:

  1. Product (House): This is the object being built, with several attributes like rooms, doors, windows, etc.
  2. Builder (HouseBuilder): This defines the steps to build a house, such as buildRooms(), buildDoors(), etc.
  3. Concrete Builder (ConcreteHouseBuilder): This implements the actual steps for building a house. It constructs a house object step by step.
  4. Director (HouseDirector): The director manages the construction process and ensures that the house is built in a particular sequence. It can handle different builders to produce different kinds of houses.
  5. Client: The client code uses the director and builder to construct different representations of the house (basic, luxury, etc.).

Benefits of the Builder Pattern:

  • Control over Construction: The builder allows you to control how a complex object is created step by step.
  • Fluent Interface: The builder pattern often uses method chaining, leading to a more readable and maintainable API.
  • Different Representations: You can create different variations of a product (e.g., basic vs. luxury house) by reusing the same construction process.
  • Immutability: The pattern helps build immutable objects since the final object is constructed through a sequence of steps without exposing setters for direct modifications.

This is a typical example of how the Builder pattern simplifies the construction of complex objects while providing flexibility to create different representations.