Builder Design Pattern
The builder design pattern is a creational design pattern.
The builder design pattern allows to separate the construction of a complex object from its representation and it allows to utilize the same construction process with different representations.
It is possible to apply the builder design pattern, when the complex object creation algorithm should be independent from the parts that make up the complex object and when the construction process requires to allow different representations for the complex object.
Design Diagram
Builder: declares an interface for creating parts of a Product type object.
ConcreteBuilder: implements the Builder interface to construct and assembles parts of the product.
Get Pawara Gunawardena’s stories in your inbox
Join Medium for free to get updates from this writer.
Director: construct a Product type object using the Builder interface.
for all objects in structure {
builder -> buildPart()
}Product: defines the complex object which is in under construction.
Implementation
Car defines the concrete complex object type.
#pragma once
#include <string>
#include <vector>
class Car {
private:
std::string chassis;
std::string engine;
std::string body;
std::vector<std::string> tyres;
public:
Car(const std::string &chassis, const std::string &engine, const std::string &body,
const std::vector<std::string> &tyres);
void describe();
~Car();
};#include <iostream>
#include "Car.h"
Car::Car(
const std::string &chassis,
const std::string &engine,
const std::string &body,
const std::vector<std::string> &tyres
) :
chassis(chassis),
engine(engine),
body(body),
tyres(tyres) {
std::cout << "Car::Car" << std::endl;
}
void Car::describe() {
std::cout << "Car "
<< "| chassis [" << this->chassis << "] "
<< "| engine [" << this->engine << "] "
<< "| body [" << this->body << "] "
<< "| tyre [" << this->tyres.back() << "] "
<< std::endl;
}
Car::~Car() {
std::cout << "Car::~Car" << std::endl;
}VehicleBuilder declares the interface for creating parts of a Vehicle type object.
#pragma once
#include <string>
#include <vector>
class VehicleBuilder {
protected:
std::string chassis;
std::string engine;
std::vector<std::string> tyres;
std::string body;
public:
VehicleBuilder();
virtual VehicleBuilder *buildChassis(const std::string &chassis);
virtual VehicleBuilder *buildEngine(const std::string &engine);
virtual VehicleBuilder *buildBody(const std::string &body);
virtual VehicleBuilder *buildTyres(const std::string &tyre);
virtual ~VehicleBuilder();
};#include <iostream>
#include "VehicleBuilder.h"
VehicleBuilder::VehicleBuilder() {
std::cout << "VehicleBuilder::VehicleBuilder" << std::endl;
}
VehicleBuilder *VehicleBuilder::buildChassis(const std::string &chassis) {
return this;
}
VehicleBuilder *VehicleBuilder::buildEngine(const std::string &engine) {
return this;
}
VehicleBuilder *VehicleBuilder::buildBody(const std::string &body) {
return this;
}
VehicleBuilder *VehicleBuilder::buildTyres(const std::string &tyre) {
return this;
}
VehicleBuilder::~VehicleBuilder() {
std::cout << "VehicleBuilder::~VehicleBuilder" << std::endl;
}CarBuilder implements the VehicleBuilder interface to construct and assembles parts of a complex Car object.
#pragma once
#include "../VehicleBuilder.h"
#include "../../Vehicle/Car.h"
class CarBuilder : public VehicleBuilder{
public:
CarBuilder();
CarBuilder *buildChassis(const std::string &chassis) override;
CarBuilder *buildEngine(const std::string &engine) override;
CarBuilder *buildBody(const std::string &body) override;
CarBuilder *buildTyres(const std::string &tyre) override;
Car* getCar();
~CarBuilder() override;
};#include <iostream>
#include "CarBuilder.h"
CarBuilder::CarBuilder() {
std::cout << "CarBuilder::CarBuilder" << std::endl;
}
Car *CarBuilder::getCar() {
return new Car(this->chassis, this->engine, this->body, this->tyres);
}
CarBuilder *CarBuilder::buildChassis(const std::string &chassis) {
this->chassis = chassis;
return this;
}
CarBuilder *CarBuilder::buildEngine(const std::string &engine) {
this->engine = engine;
return this;
}
CarBuilder *CarBuilder::buildBody(const std::string &body) {
this->body = body;
return this;
}
CarBuilder *CarBuilder::buildTyres(const std::string &tyre) {
this->tyres.push_back(tyre);
this->tyres.push_back(tyre);
this->tyres.push_back(tyre);
this->tyres.push_back(tyre);
return this;
}
CarBuilder::~CarBuilder() {
std::cout << "CarBuilder::~CarBuilder" << std::endl;
}Director constructs complex Car type objects using the VehicleBuilder interface.
#pragma once
#include <memory>
#include "../Builder/VehicleBuilder.h"
class Director {
private:
std::shared_ptr<VehicleBuilder> vehicleBuilder;
public:
explicit Director(std::shared_ptr<VehicleBuilder> vehicleBuilder);
virtual ~Director();
void constructStandardVehicle();
};#include <iostream>
#include <utility>
#include "Director.h"
Director::Director(std::shared_ptr<VehicleBuilder> vehicleBuilder) : vehicleBuilder(std::move(vehicleBuilder)) {
std::cout << "Director::Director" << std::endl;
}
void Director::constructStandardVehicle() {
vehicleBuilder
->buildChassis("standard_chassis")
->buildBody("standard_body")
->buildEngine("standard_engine")
->buildTyres("standard_tyre");
}
Director::~Director() {
std::cout << "Director::~Director" << std::endl;
}A client can use the VehicleBuilder and Director to create complex Car type objects.
#include <memory>
#include "Builder/Impl/CarBuilder.h"
#include "Director/Director.h"
int main() {
std::shared_ptr<CarBuilder> carBuilder = std::make_shared<CarBuilder>();
std::unique_ptr<Director> director = std::make_unique<Director>(carBuilder);
director->constructStandardVehicle();
std::unique_ptr<Car> car(carBuilder->getCar());
car->describe();
return 0;
}





