Welcome back! So far, we've covered various creational design patterns like the Singleton Pattern, Factory Method Pattern, and Abstract Factory Pattern. These patterns have helped you control and simplify object creation in your programs. Today, we are delving into another powerful creational pattern — the Builder Pattern. This pattern allows you to construct complex objects step by step, making the creation process more manageable and modular.
In this lesson, you will learn how to implement the Builder Pattern in C++. Specifically, you'll understand how to:
Director
class to manage the construction process.Here's a snippet of the code you'll work with:
The House.hpp
file to define the House
class — the product being constructed:
C++1#include <iostream> 2#include <string> 3 4// Product House that will be constructed using builder pattern 5class House { 6public: 7 // Setters for the house properties - foundation, structure, and roof 8 void setFoundation(const std::string& foundation) { this->foundation = foundation; } 9 void setStructure(const std::string& structure) { this->structure = structure; } 10 void setRoof(const std::string& roof) { this->roof = roof; } 11 12 // Display the house properties 13 void showHouse() { 14 std::cout << "House with " << foundation << ", " << structure << ", and " << roof << "." << std::endl; 15 } 16private: 17 std::string foundation; 18 std::string structure; 19 std::string roof; 20};
The HouseBuilder.hpp
file to define the HouseBuilder
interface:
C++1// Abstract class for HouseBuilder with methods to build foundation, structure, and roof 2class HouseBuilder { 3public: 4 virtual void buildFoundation() = 0; 5 virtual void buildStructure() = 0; 6 virtual void buildRoof() = 0; 7 virtual House* getHouse() = 0; 8};
The ConcreteHouseBuilder.hpp
file to implement the HouseBuilder
interface:
C++1// Concrete builder class for constructing a house with concrete foundation, structure, and roof 2class ConcreteHouseBuilder : public HouseBuilder { 3public: 4 ConcreteHouseBuilder() { house = new House(); } 5 ~ConcreteHouseBuilder() { delete house; } 6 void buildFoundation() override { 7 house->setFoundation("Concrete Foundation"); 8 } 9 void buildStructure() override { 10 house->setStructure("Concrete Structure"); 11 } 12 void buildRoof() override { 13 house->setRoof("Concrete Roof"); 14 } 15 House* getHouse() override { 16 return house; 17 } 18 19private: 20 House* house; 21};
The WoodenHouseBuilder.hpp
to implement the HouseBuilder
interface:
C++1// Concrete builder class for constructing a house with wooden foundation, structure, and roof 2class WoodenHouseBuilder : public HouseBuilder { 3public: 4 WoodenHouseBuilder() { house = new House(); } 5 ~WoodenHouseBuilder() { delete house; } 6 void buildFoundation() override { 7 house->setFoundation("Wooden Foundation"); 8 } 9 void buildStructure() override { 10 house->setStructure("Wooden Structure"); 11 } 12 void buildRoof() override { 13 house->setRoof("Wooden Roof"); 14 } 15 House* getHouse() override { 16 return house; 17 } 18 19private: 20 House* house; 21};
The BrickHouseBuilder.hpp
to implement the HouseBuilder
interface:
C++1// Concrete builder class for constructing a house with brick foundation, structure, and roof 2class BrickHouseBuilder : public HouseBuilder { 3public: 4 BrickHouseBuilder() { house = new House(); } 5 ~BrickHouseBuilder() { delete house; } 6 void buildFoundation() override { 7 house->setFoundation("Brick Foundation"); 8 } 9 void buildStructure() override { 10 house->setStructure("Brick Structure"); 11 } 12 void buildRoof() override { 13 house->setRoof("Brick Roof"); 14 } 15 House* getHouse() override { 16 return house; 17 } 18 19private: 20 House* house; 21};
The main.cpp
file to demonstrate the Builder Pattern:
C++1// Director class to manage the construction process by encapsulating the steps within the `constructHouse` method 2class Director { 3public: 4 void setBuilder(HouseBuilder* builder) { 5 this->builder = builder; 6 } 7 House* constructHouse() { 8 builder->buildFoundation(); 9 builder->buildStructure(); 10 builder->buildRoof(); 11 return builder->getHouse(); 12 } 13private: 14 HouseBuilder* builder; 15}; 16int main() { 17 Director director; // Director to manage the construction process 18 BrickHouseBuilder builder; // Concrete builder to build a brick house 19 director.setBuilder(&builder); // Set the builder to construct a brick house 20 House* house = director.constructHouse(); // Construct the house 21 house->showHouse(); 22 return 0; 23}
This example demonstrates how to use the Builder Pattern to create a House
object step by step.
The Builder Pattern has the following components:
House
is the product.HouseBuilder
is the builder.ConcreteHouseBuilder
, WoodenHouseBuilder
, and BrickHouseBuilder
are concrete builders. In real-world scenarios the builder method (the constructHouse in this example) can be more complex and can have multiple steps and conditions to build the actual product, but for simplicity we just call the three methods to build the product.The Director
class manages the construction process by using a builder to create the product. In this example, the Director
class sets the builder to BrickHouseBuilder
and constructs a House
object.
The Builder Pattern is useful in the following scenarios:
Let's also understand the pros and cons of the Builder Pattern:
The Builder Pattern is crucial for constructing complex objects in a controlled manner. It offers several advantages:
These features make the Builder Pattern especially useful for constructing objects that require multiple configurations or assemblies, like graphical user interfaces, parsing objects in data processing, or even complex game scenarios.
By grasping the Builder Pattern, you'll enhance your ability to design flexible, maintainable, and scalable software architectures. Ready to dive in and get hands-on experience? Let's build something amazing together.