Builder Pattern

Introduction:

Builder is a creational design pattern that lets you construct complex object step by step. The pattern allows you to create different types and representation of an object using the same construction code. 

Builder pattern suggest that extract the object construction code from its own class , and move it to separate class called builders. This pattern organize the object construction into set of steps. We no need to call all the steps. We need to invoke only the step which is required to build the 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.

You can go further and extract a series of calls to the builder steps you use to construct a product into a separate class called director. The director class defines the order in which to execute the building steps, while the builder provides the implementation for those steps.

source: refactoring guru

























Implementation:

Design a program to create Car and Manual object from the same builder interface.

Sourcecode:https://github.com/krishnaKSA/design_patterns_cplusplus/blob/main/BuilderPattern/BuilderPattern.hpp

Class diagram:



Product class:

//Product class
    //Car 
    class Car
    {
        private:
        uint8_t seats;
        uint8_t airbag;
        bool gps;
        bool rearCamera;
        bool sportsEngine;
        uint8_t doors;

        public:
        Car()
        {

        }
        void setSeats(uint8_t seats)
        {
            this->seats = seats;
        }
        void setAirbags(uint8_t airbags)
        {
            this->airbag = airbags;
        }
        void setGps(bool gps)
        {
            this->gps = gps;
        }
        void setRearCamera(bool rearCamera)
        {
            this->rearCamera = rearCamera;
        }
        void setSportsEngine(bool sportsEngine)
        {
            this->sportsEngine = sportsEngine;
        }
        void setDoors(uint8_t doors)
        {
            this->doors = doors;
        }
    };

    //Car Manual
    class CarManual
    {
        private:
        uint8_t seats;
        uint8_t airbag;
        bool gps;
        bool rearCamera;
        bool sportsEngine;
        uint8_t doors;

        public:
        CarManual(){}
        void setSeats(uint8_t seats)
        {
            this->seats = seats;
        }
        void setAirbags(uint8_t airbags)
        {
            this->airbag = airbags;
        }
        void setGps(bool gps)
        {
            this->gps = gps;
        }
        void setRearCamera(bool rearCamera)
        {
            this->rearCamera = rearCamera;
        }
        void setSportsEngine(bool sportsEngine)
        {
            this->sportsEngine = sportsEngine;
        }
        void setDoors(uint8_t doors)
        {
            this->doors = doors;
        }
        
        uint8_t getSeats()
        {
            return seats;
        }
    };

Builder Interface class:

    //BuilderInterface
    class IBuilder
    {
        public:
        virtual void reset() = 0;
        virtual void buildDoors(uint8_t value) = 0;
        virtual void buildAirbags(uint8_t value) = 0;
        virtual void buildSeats(uint8_t value) = 0;
        virtual void buildEngine(bool value) = 0;
        virtual void buildGps(bool value) = 0;
        virtual void buildRearCamera(bool value) = 0;
    };

Concrete builder classes:

    //Manual Car builder class
    class ManualCarBuilder : public IBuilder
    {
        private:
        Car* car;
        public:
        void reset()
        {
            car = new Car();
        }
        Car* getProduct()
        {
            return car;
        }
        void buildDoors(uint8_t value) override
        {
            car->setDoors(value);
        }
        void buildAirbags(uint8_t value) override
        {
            car->setAirbags(value);
        }
        void buildSeats(uint8_t value) override
        {
            car->setSeats(value);
        }
        void buildEngine(bool value) override
        {
            car->setSportsEngine(value);
        }
        void buildGps(bool value) override
        {
            car->setGps(value);
        }
        void buildRearCamera(bool value) override
        {
            car->setRearCamera(value);
        }
    };

    //Car manual builder class
    class ManualBuilder : public IBuilder
    {
        private:
        CarManual* manual;
        public:
        void reset()
        {
            manual = new CarManual();
        }
        CarManual* getProduct()
        {
            return manual;
        }
        void buildDoors(uint8_t value) override
        {
            manual->setDoors(value);
        }
        void buildAirbags(uint8_t value) override
        {
            manual->setAirbags(value);
        }
        void buildSeats(uint8_t value) override
        {
            manual->setSeats(value);
        }
        void buildEngine(bool value) override
        {
            manual->setSportsEngine(value);
        }
        void buildGps(bool value) override
        {
            manual->setGps(value);
        }
        void buildRearCamera(bool value) override
        {
            manual->setRearCamera(value);
        }
    };

Director class:

    //director class
    class Director
    {
        private:
        IBuilder* builder;
        public:
        Director()
        {
            builder = nullptr;
        }
        //set builder object
        void setBuilder(IBuilder* builder)
        {
            this->builder = builder;
        }
        //Build normal car
        void BuildNormalCar()
        {
            this->builder->reset();
            this->builder->buildAirbags(2);
            this->builder->buildDoors(4);
            this->builder->buildSeats(4);
            this->builder->buildEngine(false);
            this->builder->buildGps(true);
            this->builder->buildRearCamera(true);
        }

        //build sports car
        void BuildSportsCar()
        {
            this->builder->reset();
            this->builder->buildAirbags(2);
            this->builder->buildDoors(2);
            this->builder->buildSeats(2);
            this->builder->buildEngine(true);
            this->builder->buildGps(true);
            this->builder->buildRearCamera(true);
        }

    };

Client code:

    void testClientCode()
    {
        ManualCarBuilder* carBuilder = new ManualCarBuilder();
        ManualBuilder* manualBuilder = new ManualBuilder();
        Director* director = new Director();
        //set car builder object
        director->setBuilder(carBuilder);
        director->BuildNormalCar();
        //set manual builder object
        director->setBuilder(manualBuilder);
        //get sports car
        director->BuildSportsCar();
        
        //get the car manual for sports car
        CarManual* manual = manualBuilder->getProduct();
    }