Skip to content

Latest commit

 

History

History
214 lines (180 loc) · 8.21 KB

1C. Builder.md

File metadata and controls

214 lines (180 loc) · 8.21 KB

Builder

The Builder Design Pattern is a creational design pattern that provides a way to construct complex objects step by step. It separates the construction of an object from its representation, allowing the same construction process to create different representations.

The Builder pattern is useful when you need to create objects that have many configurable properties, and you want to simplify the object creation process by providing a clear and readable API.

image

// Builder Interface
interface Builder {
    void setBrand(String brand);
    void setModel(String model);
    void setYear(int year);
    void setColor(String color);
    void setNumberOfSeats(int numberOfSeats);
    void reset();
}

class Car {
    // A car can have brand, model, year ...
    private String brand;
    private String model;
    private int year;
    private String color;
    private int numberOfSeats;

    public Car(String brand, String model, int year, String color, int numberOfSeats) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.color = color;
        this.numberOfSeats = numberOfSeats;
    }

    // Getter ...
    
    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", model='" + model + '\'' +
                ", year=" + year +
                ", color='" + color + '\'' +
                ", numberOfSeats=" + numberOfSeats +
                '}';
    }
}

class Manual {
    // Each car should have a user manual that corresponds to the car's configuration and describes all its features.
    private String brand;
    private String model;
    private int year;
    private String color;
    private int numberOfSeats;

    public Manual(String brand, String model, int year, String color, int numberOfSeats) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.color = color;
        this.numberOfSeats = numberOfSeats;
    }

    // Getter
   
    @Override
    public String toString() {
        return "Manual{" +
                "brand='" + brand + '\'' +
                ", model='" + model + '\'' +
                ", year=" + year +
                ", color='" + color + '\'' +
                ", numberOfSeats=" + numberOfSeats +
                '}';
    }

    public void printInfo() {
        System.out.println("INFO: ...");
    }
}

// Concrete Builder
class CarBuilder implements Builder {
    private String brand;
    private String model;
    private int year;
    private String color;
    private int numberOfSeats;

    // Setter (@Override)
    @Override
    public void setBrand(String brand) {
        this.brand = brand;
    }
    ...

    @Override
    public void reset() {
        this.brand = null;
        this.model = null;
        this.year = 0;
        this.color = null;
        this.numberOfSeats = 0;
    }

    public Car getProduct() {
        return new Car(brand, model, year, color, numberOfSeats);
    }
}

// Concrete Builder
class ManualBuilder implements Builder {
    private String brand;
    private String model;
    private int year;
    private String color;
    private int numberOfSeats;

    // Setter (@Override)
    // Manual instructions of the car specifications
    @Override
    public void setBrand(String brand) {
        this.brand = brand;
    }
    ...

    @Override
    public void reset() {
        this.brand = null;
        this.model = null;
        this.year = 0;
        this.color = null;
        this.numberOfSeats = 0;
    }

    public Manual getProduct() {
        return new Manual(this.brand, this.model, year, color, numberOfSeats);
    }
}

// Director
class Director {
    public void constructCar(Builder builder) {
        builder.reset();
        builder.setBrand("Ferrari");
        builder.setModel("488 GTB");
        builder.setYear(2023);
        builder.setColor("Red");
        builder.setNumberOfSeats(2);
    }

    public void constructManual(Builder builder) {
        builder.reset();
        builder.setBrand("Ferrari");
        builder.setModel("488 GTB");
        builder.setYear(2023);
        builder.setColor("Red");
        builder.setNumberOfSeats(2);
    }
}

public class Main {
    public static void main(String[] args) {
        Director director = new Director();
        CarBuilder builder = new CarBuilder();
        director.constructCar(builder);
        Car car = builder.getProduct();
        System.out.println(car);  // Car{brand='Ferrari', model='488 GTB', year=2023, color='Red', numberOfSeats=2}

        ManualBuilder manualBuilder = new ManualBuilder();
        director.constructManual(manualBuilder);
        Manual manual = manualBuilder.getProduct();
        System.out.println(manual);  // Manual{brand='Ferrari', model='488 GTB', year=2023, color='Red', numberOfSeats=2}
        manual.printInfo();  // INFO: ...
    }
}
  1. The Builder interface:
  • It defines the common methods that builders must implement: setBrand, setModel, setYear, setColor, setNumberOfSeats, and reset.
  • The reset method allows resetting the builder's internal state, preparing it for a fresh construction process.
  1. The Car class:
  • It represents the product object that we want to construct using the builder.
  • It has various properties such as brand, model, year, color, and numberOfSeats.
  • The class has a constructor that takes these properties as parameters and sets them.
  1. The CarBuilder class:
  • It implements the Builder interface, providing the implementations for all the methods.
  • It also has private fields to hold the properties of the car being constructed: brand, model, year, color, and numberOfSeats.
  • The setXXX methods allow setting individual properties of the car.
  • The reset method resets the builder's state by setting all the properties to their initial or default values.
  • The getProduct method creates and returns a new Car object with the configured properties.
  1. The Director class:
  • It is responsible for the construction process and uses a builder to create a Car or Manual object.
  • The construction methods (constructManual, constructCar) takes a Builder object as a parameter and constructs an object accordingly.
  • Before setting the properties of the an object, it calls the reset method on the builder to ensure a clean state.

The CarBuilder class separates the construction of the Car object from its representation, allowing step-by-step configuration of its properties. The Director class coordinates the construction process by providing a method to construct a sports car. The Builder interface provides a consistent interface for different builders to construct objects. This pattern promotes a clear and readable API for building complex objects.

The Builder Design Pattern allows you to construct complex objects step by step, providing a flexible and readable way to configure object properties.

Builder Design Pattern Summary:

Use the Builder pattern when you want your code to be able to create different Object representations. For instance instead of having just a CarBuilder class, there can be classes like ManualBuilder, TruckBuilder, ... that all implements the Builder interface but create different kinds of Object.

  • Moreover, the Director could have methods like void makeSUV(builder Builder) or void makeSportsCar(builder Builder) that both commands the builder Builder to create an object Car, but the implementations could differ (eg. makeSUV can have builder.setNumberOfSeats(4); while makeSportsCar can have builder.setNumberOfSeats(2); ...)
  • A builder doesn’t expose the unfinished Object while running construction steps. This prevents the client code from fetching an incomplete result.
  • Let's you construct unrelated Object that don't follow a common interface like Manual and Car. (eg. Manual have printInfo but Car doesn't)
    • However in the example above, Manual object doesn't implement any Interface, but there can be if needed, Car could implement the Vehicle interface ...

image