C++ Builder Design Pattern:
It separates the construction process of complex object from its representation so that the same construction process can be used to create different representations.
In layman language:
This design pattern will create ONE complex object (many steps are required to create it), we can create different type of object (one at a time) but construction process will be same for all type of object.
Example:
Different car model like i10 or i20 of Hyundai. If new model comes then we can add a new concrete builder for new model.
There are 3 part:
- Director: It has a builder instance, it define the construction process and this same construction process can be used to create different type of objects using different concrete builders.
- Builder: It is an abstract class, final product will be created by subclass builder
- Concrete Builder : It will create the actual object.
Class Diagram of Builder Pattern:
Sequence diagram of Builder pattern:
When will we use Builder Design pattern:
When we want to create a single complex object(many steps are involved in it) of different types and want to use same construction process and there is possibility we might add new type of object in future.
Why will we use Builder Design pattern:
Because Builder gives the flexibility to create an object of different type using same construction process and its very easy to extend in future. If we extend it in future to add new builder (to create a new object) then we need to do very small change in client side (it will not pollute the client code).
It is very easy to extend to support new object.
Class Diagram of Real Example:
source code with example in c++11:
/* * File:builder.cpp * This file is described the builder Design Pattern with help of example * Author: Alpha Master * Date: 17 April 2021 */ //Header File #include<iostream> #include<memory> //Engine class Engine { int m_Power; public: void setPower(int pw) { m_Power = pw; } int getPower(){ return m_Power;} }; //Body class Body { int m_BodySize; public: void setBody(int sz) { m_BodySize = sz; } int getBody() { return m_BodySize;} }; //Wheel class Wheel { int m_WheelSize; public: void setWheel(int sz) { m_WheelSize = sz; } int getWheel() { return m_WheelSize;} }; //Car Class class Car { //Data member MUST BE PRIVATE but here I am using as public for demo example public: Engine m_eng; Body m_body; Wheel m_wh; public: }; //HyundaiCarBuilder class IHyundaiCarBuilder { protected: std::unique_ptr<Car>m_car; public: virtual void BuildEngine() = 0; virtual void BuildBody() = 0; virtual void BuildWheel() = 0; virtual std::unique_ptr<Car> GetCar() = 0; }; //Car_i10Builder class Car_i10Builder: public IHyundaiCarBuilder { public: Car_i10Builder() { m_car.reset(new Car);} ~Car_i10Builder() {} void BuildEngine(){ m_car->m_eng.setPower(1000);} void BuildBody(){ m_car->m_body.setBody(100);} void BuildWheel(){m_car->m_wh.setWheel(10);} std::unique_ptr<Car> GetCar() { std::cout<<"Car i10 is ready"<<std::endl; return std::move(m_car); } }; //Car_i20Builder class Car_i20Builder: public IHyundaiCarBuilder { public: Car_i20Builder() { m_car.reset(new Car); } ~Car_i20Builder() {} void BuildEngine(){ m_car->m_eng.setPower(2000);} void BuildBody(){ m_car->m_body.setBody(200);} void BuildWheel(){m_car->m_wh.setWheel(20);} std::unique_ptr<Car> GetCar() { std::cout<<"Car i20 is ready"<<std::endl; return std::move(m_car); } }; //Director class Director { std::unique_ptr<IHyundaiCarBuilder>m_builder; public: Director() {} void SetBuilder(std::unique_ptr<IHyundaiCarBuilder>&build) { m_builder.reset(build.release()); } void Construct() { m_builder->BuildEngine(); m_builder->BuildBody(); m_builder->BuildWheel(); } std::unique_ptr<Car> GetCar() { std::cout<<"Get Car in Director"<<std::endl; return std::move(m_builder->GetCar()); } }; //Client int main() { std::cout<<"Builder Design Pattern"<<std::endl; std::cout<<"Using i10 Builder for building i10"<<std::endl; std::unique_ptr<IHyundaiCarBuilder>build { new Car_i10Builder}; std::unique_ptr<Director>dir{new Director}; dir->SetBuilder(build); dir->Construct(); std::unique_ptr<Car>car{dir->GetCar()}; std::cout<<"Engine Power:"<<(*car).m_eng.getPower()<<std::endl; std::cout<<"Body Size:"<<(*car).m_body.getBody()<<std::endl; std::cout<<"Wheel Size:"<<(*car).m_wh.getWheel()<<std::endl; std::cout<<"Using i20 Builder for building i20"<<std::endl; build.reset(new Car_i20Builder); dir->SetBuilder(build); dir->Construct(); car.reset(dir->GetCar().release()); std::cout<<"Engine Power:"<<(*car).m_eng.getPower()<<std::endl; std::cout<<"Body Size:"<<(*car).m_body.getBody()<<std::endl; std::cout<<"Wheel Size:"<<(*car).m_wh.getWheel()<<std::endl; return 0; }
Output:
Builder Design Pattern Using i10 Builder for building i10 Get Car in Director Car i10 is ready Engine Power:1000 Body Size:100 Wheel Size:10 Using i20 Builder for building i20 Get Car in Director Car i20 is ready Engine Power:2000 Body Size:200 Wheel Size:20