Builder Pattern
- The Builder design pattern is used 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 of the object.
- It is useful when an object can have multiple variations or configurations, and you want to hide the complexity of object creation from the client.
- In simple terms, think of a builder as a blueprint for building something, like a house. The builder knows the steps to construct the house, but it can be used to build different types of houses with various features.
Builder Pattern C++ Example:
Let’s create a simple example of the Builder pattern to construct a Computer
object. We’ll have a ComputerBuilder
as the builder, and Computer
as the complex object to be built.
#include <iostream>
#include <string>
// Complex object to be built
class Computer {
public:
void setCPU(const std::string& cpu) {
cpu_ = cpu;
}
void setGPU(const std::string& gpu) {
gpu_ = gpu;
}
void setRAM(int ram) {
ram_ = ram;
}
void displaySpecs() const {
std::cout << "Computer Specs:" << std::endl;
std::cout << "CPU: " << cpu_ << std::endl;
std::cout << "GPU: " << gpu_ << std::endl;
std::cout << "RAM: " << ram_ << " GB" << std::endl;
}
private:
std::string cpu_;
std::string gpu_;
int ram_;
};
// Builder interface
class ComputerBuilder {
public:
virtual void setCPU() = 0;
virtual void setGPU() = 0;
virtual void setRAM() = 0;
virtual Computer* getResult() = 0;
};
// Concrete builder to build a gaming computer
class GamingComputerBuilder : public ComputerBuilder {
public:
GamingComputerBuilder() {
computer_ = new Computer();
}
void setCPU() override {
computer_->setCPU("Intel Core i7");
}
void setGPU() override {
computer_->setGPU("Nvidia RTX 3080");
}
void setRAM() override {
computer_->setRAM(16);
}
Computer* getResult() override {
return computer_;
}
private:
Computer* computer_;
};
// Concrete builder to build an office computer
class OfficeComputerBuilder : public ComputerBuilder {
public:
OfficeComputerBuilder() {
computer_ = new Computer();
}
void setCPU() override {
computer_->setCPU("Intel Core i5");
}
void setGPU() override {
// Office computer doesn't have a dedicated GPU
computer_->setGPU("Integrated");
}
void setRAM() override {
computer_->setRAM(8);
}
Computer* getResult() override {
return computer_;
}
private:
Computer* computer_;
};
// Director class to construct the computer
class Director {
public:
void setBuilder(ComputerBuilder* builder) {
builder_ = builder;
}
Computer* construct() {
builder_->setCPU();
builder_->setGPU();
builder_->setRAM();
return builder_->getResult();
}
private:
ComputerBuilder* builder_;
};
int main() {
// Create a Director
Director director;
// Create a GamingComputerBuilder and construct a gaming computer
GamingComputerBuilder gamingBuilder;
director.setBuilder(&gamingBuilder);
Computer* gamingComputer = director.construct();
// Create an OfficeComputerBuilder and construct an office computer
OfficeComputerBuilder officeBuilder;
director.setBuilder(&officeBuilder);
Computer* officeComputer = director.construct();
// Display the computer specs
gamingComputer->displaySpecs();
officeComputer->displaySpecs();
delete gamingComputer;
delete officeComputer;
return 0;
}
Explanation of Code:
In this example, we have a Computer
class, which is the complex object we want to build. It has methods to set its components, such as CPU, GPU, and RAM, and a method to display its specifications.
We create a ComputerBuilder
interface with methods to set CPU, GPU, and RAM, and to get the final Computer
object. The GamingComputerBuilder
and OfficeComputerBuilder
are concrete builders that implement the ComputerBuilder
interface to build different types of computers (gaming and office).
We have a Director
class, which is responsible for directing the construction process. It has a method setBuilder()
to set the appropriate builder and a method construct()
to build the computer step-by-step.
In the main()
function, we demonstrate how the Builder pattern works. We create a Director
and use different builders to construct a gaming computer and an office computer. Each builder knows the steps to construct its specific type of computer.
The Builder pattern is helpful when creating complex objects with multiple configurations. It abstracts the object construction process, making it easier to create variations of the object without exposing the complexity to the client. By using the Builder pattern, you can construct objects step-by-step while keeping the code more organized and maintainable.