The Builder Design Pattern is one of the most widely used patterns in software engineering. It is a creational pattern that allows you to separate the construction of complex objects from their representation.
The main idea behind the Builder Design Pattern is to create a separate class (the Builder) that is responsible for creating complex objects. The client code then interacts with the Builder to build the desired object. The Builder uses a step-by-step approach to build the object, and each step can be customized to fit the specific needs of the client.
Note: I’ll be discussing the examples in Python and C++
I posted one post before on the same topic. Here, I tried to explain it differently. Please, let me know which tone suits you best.
Problem with traditional approach
Let us see what kind of problem it can solve.
The Builder Pattern solves a very specific problem: Telescoping Constructors. To understand it, let us suppose we have the following constructor definitions for class Vehicle
<span>public</span> <span>Car</span><span>(</span><span>int</span> <span>id</span><span>,</span> <span>String</span> <span>name</span><span>)</span><span>{</span><span>this</span><span>(</span><span>id</span><span>,</span> <span>name</span><span>,</span> <span>0</span><span>,</span> <span>0</span><span>);</span><span>}</span><span>public</span> <span>Car</span><span>(</span><span>int</span> <span>id</span><span>,</span> <span>String</span> <span>name</span><span>,</span> <span>int</span> <span>number_of_tyres</span><span>)</span><span>{</span><span>this</span><span>(</span><span>id</span><span>,</span> <span>name</span><span>,</span> <span>number_of_tyres</span><span>,</span> <span>0</span><span>);</span><span>}</span><span>public</span> <span>Car</span><span>(</span><span>int</span> <span>id</span><span>,</span> <span>String</span> <span>name</span><span>)</span> <span>{</span> <span>this</span><span>(</span><span>id</span><span>,</span> <span>name</span><span>,</span> <span>0</span><span>,</span> <span>0</span><span>);</span> <span>}</span> <span>public</span> <span>Car</span><span>(</span><span>int</span> <span>id</span><span>,</span> <span>String</span> <span>name</span><span>,</span> <span>int</span> <span>number_of_tyres</span><span>)</span> <span>{</span> <span>this</span><span>(</span><span>id</span><span>,</span> <span>name</span><span>,</span> <span>number_of_tyres</span><span>,</span> <span>0</span><span>);</span> <span>}</span>public Car(int id, String name) { this(id, name, 0, 0); } public Car(int id, String name, int number_of_tyres) { this(id, name, number_of_tyres, 0); }
Enter fullscreen mode Exit fullscreen mode
This might not look like an issue at the earlier stages but if you have eight optional parameters and you want to represent every useful combination, you’ll need 256 constructors. This would be very cumbersome and would result in a lot of boilerplate code.
Let’s look at an example to see how the Builder Design Pattern works in practice.
Builder Design Pattern Participants
First, let’s look at various participants of builder design pattern:
-
Product : First, we create the product’s blueprint or interface, which will define the steps required to build the product. This interface can be implemented by different classes to produce different products.
-
Concrete Builder : Next, we create a concrete builder class that implements the product’s interface and provides a method for each step required to build the product.
The concrete builder class also has a method to return the final product.
- Director : Finally, we create a director class that will use the concrete builder to build the product. The director class is responsible for invoking the concrete builder’s methods in the correct order to produce the final product.
Builder design pattern Diagrams
Let’s see through diagrams how builder design pattern looks or works.
Imagine we’re building the same car as above. The car has many attributes, such as the engine type, the number of doors, and the color.
Sequence diagram
Below are the steps required to build a car,
Remember, we can use different concrete builders to create different types of cars with different attributes.
Below is the source code for above sequnce diagram in PlantUML:
@startumltitle Car Building Sequence Diagramactor ClientClient -> CarDirector: create directorClient -> AudiCarBuilder: create audi builderCarDirector -> CarDirector: set builder to audi builderClient -> CarDirector: build carCarDirector -> AudiCarBuilder: add engineAudiCarBuilder -> Car: set engineCarDirector -> AudiCarBuilder: add doorsAudiCarBuilder -> Car: set doorsCarDirector -> AudiCarBuilder: paint carAudiCarBuilder -> Car: paintCarDirector -> AudiCarBuilder: get carAudiCarBuilder -> Car: return carCarDirector -> Client: return car@enduml@startuml title Car Building Sequence Diagram actor Client Client -> CarDirector: create director Client -> AudiCarBuilder: create audi builder CarDirector -> CarDirector: set builder to audi builder Client -> CarDirector: build car CarDirector -> AudiCarBuilder: add engine AudiCarBuilder -> Car: set engine CarDirector -> AudiCarBuilder: add doors AudiCarBuilder -> Car: set doors CarDirector -> AudiCarBuilder: paint car AudiCarBuilder -> Car: paint CarDirector -> AudiCarBuilder: get car AudiCarBuilder -> Car: return car CarDirector -> Client: return car @enduml@startuml title Car Building Sequence Diagram actor Client Client -> CarDirector: create director Client -> AudiCarBuilder: create audi builder CarDirector -> CarDirector: set builder to audi builder Client -> CarDirector: build car CarDirector -> AudiCarBuilder: add engine AudiCarBuilder -> Car: set engine CarDirector -> AudiCarBuilder: add doors AudiCarBuilder -> Car: set doors CarDirector -> AudiCarBuilder: paint car AudiCarBuilder -> Car: paint CarDirector -> AudiCarBuilder: get car AudiCarBuilder -> Car: return car CarDirector -> Client: return car @enduml
Enter fullscreen mode Exit fullscreen mode
Class Diagrams
To give you a snapshot, this is how our class skeletons would look like:
In plantUML, it looks as:
@startumlclass Car {- engine_type: str- num_doors: int- color: str+ set_engine(engine_type: str): void+ set_doors(num_doors: int): void+ paint(color: str): void}class AudiCarBuilder {- car: Car+ AudiCarBuilder()+ add_engine(engine_type: str): void+ add_doors(num_doors: int): void+ paint(color: str): void+ get_car(): Car}class CarDirector {- builder: ICarBuilder+ CarDirector(audiCarBuilder: ICarBuilder)+ build_car(): Car}AudiCarBuilder -> Car: 1CarDirector -> AudiCarBuilder@enduml@startuml class Car { - engine_type: str - num_doors: int - color: str + set_engine(engine_type: str): void + set_doors(num_doors: int): void + paint(color: str): void } class AudiCarBuilder { - car: Car + AudiCarBuilder() + add_engine(engine_type: str): void + add_doors(num_doors: int): void + paint(color: str): void + get_car(): Car } class CarDirector { - builder: ICarBuilder + CarDirector(audiCarBuilder: ICarBuilder) + build_car(): Car } AudiCarBuilder -> Car: 1 CarDirector -> AudiCarBuilder @enduml@startuml class Car { - engine_type: str - num_doors: int - color: str + set_engine(engine_type: str): void + set_doors(num_doors: int): void + paint(color: str): void } class AudiCarBuilder { - car: Car + AudiCarBuilder() + add_engine(engine_type: str): void + add_doors(num_doors: int): void + paint(color: str): void + get_car(): Car } class CarDirector { - builder: ICarBuilder + CarDirector(audiCarBuilder: ICarBuilder) + build_car(): Car } AudiCarBuilder -> Car: 1 CarDirector -> AudiCarBuilder @enduml
Enter fullscreen mode Exit fullscreen mode
Builder design pattern implementation
Step 1 Declare interface of our final product
First, let’s define the product, which is Car.
<span>class</span> <span>Car</span><span>:</span><span>def</span> <span>__init__</span><span>(</span><span>self</span><span>):</span><span>self</span><span>.</span><span>engine_type</span> <span>=</span> <span>None</span><span>self</span><span>.</span><span>num_doors</span> <span>=</span> <span>None</span><span>self</span><span>.</span><span>color</span> <span>=</span> <span>None</span><span>def</span> <span>add_engine</span><span>(</span><span>self</span><span>,</span> <span>engine_type</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>engine_type</span> <span>=</span> <span>engine_type</span><span>def</span> <span>add_doors</span><span>(</span><span>self</span><span>,</span> <span>num_doors</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>num_doors</span> <span>=</span> <span>num_doors</span><span>def</span> <span>paint</span><span>(</span><span>self</span><span>,</span> <span>color</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>color</span> <span>=</span> <span>color</span><span>class</span> <span>Car</span><span>:</span> <span>def</span> <span>__init__</span><span>(</span><span>self</span><span>):</span> <span>self</span><span>.</span><span>engine_type</span> <span>=</span> <span>None</span> <span>self</span><span>.</span><span>num_doors</span> <span>=</span> <span>None</span> <span>self</span><span>.</span><span>color</span> <span>=</span> <span>None</span> <span>def</span> <span>add_engine</span><span>(</span><span>self</span><span>,</span> <span>engine_type</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>engine_type</span> <span>=</span> <span>engine_type</span> <span>def</span> <span>add_doors</span><span>(</span><span>self</span><span>,</span> <span>num_doors</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>num_doors</span> <span>=</span> <span>num_doors</span> <span>def</span> <span>paint</span><span>(</span><span>self</span><span>,</span> <span>color</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>color</span> <span>=</span> <span>color</span>class Car: def __init__(self): self.engine_type = None self.num_doors = None self.color = None def add_engine(self, engine_type): self.car.engine_type = engine_type def add_doors(self, num_doors): self.car.num_doors = num_doors def paint(self, color): self.car.color = color
Enter fullscreen mode Exit fullscreen mode
Our Final product Car
has engine type, the number of doors, and the color.
Step 2. Define the Builder class to implement each build step
Next step is to define the concrete builder class that implements the method for each step required to build the above product.
Remember, we also need to define a method to return the final product.
<span>class</span> <span>AudiCarBuilder</span><span>:</span><span>def</span> <span>__init__</span><span>(</span><span>self</span><span>):</span><span>self</span><span>.</span><span>car</span> <span>=</span> <span>Car</span><span>()</span><span>def</span> <span>add_engine</span><span>(</span><span>self</span><span>,</span> <span>engine_type</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>set_engine</span><span>(</span><span>engine_type</span><span>)</span><span>def</span> <span>add_doors</span><span>(</span><span>self</span><span>,</span> <span>num_doors</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>set_doors</span><span>(</span><span>num_doors</span><span>)</span><span>def</span> <span>paint</span><span>(</span><span>self</span><span>,</span> <span>color</span><span>):</span><span>self</span><span>.</span><span>car</span><span>.</span><span>paint</span><span>(</span> <span>=</span> <span>)</span><span>color</span><span>)</span><span>def</span> <span>get_car</span><span>(</span><span>self</span><span>):</span><span>return</span> <span>self</span><span>.</span><span>car</span><span>class</span> <span>AudiCarBuilder</span><span>:</span> <span>def</span> <span>__init__</span><span>(</span><span>self</span><span>):</span> <span>self</span><span>.</span><span>car</span> <span>=</span> <span>Car</span><span>()</span> <span>def</span> <span>add_engine</span><span>(</span><span>self</span><span>,</span> <span>engine_type</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>set_engine</span><span>(</span><span>engine_type</span><span>)</span> <span>def</span> <span>add_doors</span><span>(</span><span>self</span><span>,</span> <span>num_doors</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>set_doors</span><span>(</span><span>num_doors</span><span>)</span> <span>def</span> <span>paint</span><span>(</span><span>self</span><span>,</span> <span>color</span><span>):</span> <span>self</span><span>.</span><span>car</span><span>.</span><span>paint</span><span>(</span> <span>=</span> <span>)</span><span>color</span><span>)</span> <span>def</span> <span>get_car</span><span>(</span><span>self</span><span>):</span> <span>return</span> <span>self</span><span>.</span><span>car</span>class AudiCarBuilder: def __init__(self): self.car = Car() def add_engine(self, engine_type): self.car.set_engine(engine_type) def add_doors(self, num_doors): self.car.set_doors(num_doors) def paint(self, color): self.car.paint( = )color) def get_car(self): return self.car
Enter fullscreen mode Exit fullscreen mode
Apart from defining various methods to build our final product, we also define the method to return it through function get_car()
.
Step 3.
Lastly, create a director class to build the final product.
Remember to invoke each construction step/method in the correct order to produce the final product. In our example is to first install the engine before attaching doors or starting painting. :happy:
<span>class</span> <span>CarDirector</span><span>:</span><span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>builder</span><span>):</span><span>self</span><span>.</span><span>builder</span> <span>=</span> <span>builder</span><span>def</span> <span>build_car</span><span>(</span><span>self</span><span>):</span><span>self</span><span>.</span><span>builder</span><span>.</span><span>add_engine</span><span>(</span><span>"V8"</span><span>)</span><span>self</span><span>.</span><span>builder</span><span>.</span><span>add_doors</span><span>(</span><span>4</span><span>)</span><span>self</span><span>.</span><span>builder</span><span>.</span><span>paint</span><span>(</span><span>"Red"</span><span>)</span><span>return</span> <span>self</span><span>.</span><span>builder</span><span>.</span><span>get_car</span><span>()</span><span>class</span> <span>CarDirector</span><span>:</span> <span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>builder</span><span>):</span> <span>self</span><span>.</span><span>builder</span> <span>=</span> <span>builder</span> <span>def</span> <span>build_car</span><span>(</span><span>self</span><span>):</span> <span>self</span><span>.</span><span>builder</span><span>.</span><span>add_engine</span><span>(</span><span>"V8"</span><span>)</span> <span>self</span><span>.</span><span>builder</span><span>.</span><span>add_doors</span><span>(</span><span>4</span><span>)</span> <span>self</span><span>.</span><span>builder</span><span>.</span><span>paint</span><span>(</span><span>"Red"</span><span>)</span> <span>return</span> <span>self</span><span>.</span><span>builder</span><span>.</span><span>get_car</span><span>()</span>class CarDirector: def __init__(self, builder): self.builder = builder def build_car(self): self.builder.add_engine("V8") self.builder.add_doors(4) self.builder.paint("Red") return self.builder.get_car()
Enter fullscreen mode Exit fullscreen mode
Our Builder implementation is now complete.
Let’s use it in our code base. It’s too easy now to use.
<span>builder</span> <span>=</span> <span>AudiCarBuilder</span><span>()</span><span>director</span> <span>=</span> <span>CarDirector</span><span>(</span><span>builder</span><span>)</span><span>car</span> <span>=</span> <span>director</span><span>.</span><span>build_car</span><span>()</span><span>print</span><span>(</span><span>f</span><span>"Engine type: </span><span>{</span><span>car</span><span>.</span><span>engine_type</span><span>}</span><span>"</span><span>)</span><span>print</span><span>(</span><span>f</span><span>"Number of doors: </span><span>{</span><span>car</span><span>.</span><span>num_doors</span><span>}</span><span>"</span><span>)</span><span>print</span><span>(</span><span>f</span><span>"Color: </span><span>{</span><span>car</span><span>.</span><span>color</span><span>}</span><span>"</span><span>)</span><span>builder</span> <span>=</span> <span>AudiCarBuilder</span><span>()</span> <span>director</span> <span>=</span> <span>CarDirector</span><span>(</span><span>builder</span><span>)</span> <span>car</span> <span>=</span> <span>director</span><span>.</span><span>build_car</span><span>()</span> <span>print</span><span>(</span><span>f</span><span>"Engine type: </span><span>{</span><span>car</span><span>.</span><span>engine_type</span><span>}</span><span>"</span><span>)</span> <span>print</span><span>(</span><span>f</span><span>"Number of doors: </span><span>{</span><span>car</span><span>.</span><span>num_doors</span><span>}</span><span>"</span><span>)</span> <span>print</span><span>(</span><span>f</span><span>"Color: </span><span>{</span><span>car</span><span>.</span><span>color</span><span>}</span><span>"</span><span>)</span>builder = AudiCarBuilder() director = CarDirector(builder) car = director.build_car() print(f"Engine type: {car.engine_type}") print(f"Number of doors: {car.num_doors}") print(f"Color: {car.color}")
Enter fullscreen mode Exit fullscreen mode
How builder pattern helped us
By using the Builder pattern, we can create different concrete builders to build different types of cars with different attributes.
We can also modify the steps required to build a car without modifying the Car class itself, making our code more flexible and easier to maintain.
Complete implementation in C++
Now, I feel it must be easy for you to understand how builder pattern can be written in C++ also. Still, for your reference I’m giving the source code here.
<span>#include</span> <span><iostream></span><span> #include</span> <span><string></span><span> </span><span>class</span> <span>Car</span> <span>{</span><span>private:</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>;</span><span>int</span> <span>num_doors</span><span>;</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>;</span><span>public:</span><span>void</span> <span>set_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>{</span><span>this</span><span>-></span><span>engine_type</span> <span>=</span> <span>engine_type</span><span>;</span><span>}</span><span>void</span> <span>set_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>{</span><span>this</span><span>-></span><span>num_doors</span> <span>=</span> <span>num_doors</span><span>;</span><span>}</span><span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>{</span><span>this</span><span>-></span><span>color</span> <span>=</span> <span>color</span><span>;</span><span>}</span><span>void</span> <span>display</span><span>()</span> <span>{</span><span>std</span><span>::</span><span>cout</span> <span><<</span> <span>"Car with "</span> <span><<</span> <span>engine_type</span> <span><<</span> <span>" engine, "</span> <span><<</span> <span>num_doors</span> <span><<</span> <span>" doors, and "</span> <span><<</span> <span>color</span> <span><<</span> <span>" color."</span> <span><<</span> <span>std</span><span>::</span><span>endl</span><span>;</span><span>}</span><span>};</span><span>class</span> <span>ICarBuilder</span> <span>{</span><span>public:</span><span>virtual</span> <span>void</span> <span>add_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>=</span> <span>0</span><span>;</span><span>virtual</span> <span>void</span> <span>add_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>=</span> <span>0</span><span>;</span><span>virtual</span> <span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>=</span> <span>0</span><span>;</span><span>virtual</span> <span>Car</span> <span>get_car</span><span>()</span> <span>=</span> <span>0</span><span>;</span><span>};</span><span>class</span> <span>AudiCarBuilder</span> <span>:</span> <span>public</span> <span>ICarBuilder</span> <span>{</span><span>private:</span><span>Car</span> <span>car</span><span>;</span><span>public:</span><span>void</span> <span>add_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>{</span><span>car</span><span>.</span><span>set_engine</span><span>(</span><span>engine_type</span><span>);</span><span>}</span><span>void</span> <span>add_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>{</span><span>car</span><span>.</span><span>set_doors</span><span>(</span><span>num_doors</span><span>);</span><span>}</span><span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>{</span><span>car</span><span>.</span><span>paint</span><span>(</span><span>color</span><span>);</span><span>}</span><span>Car</span> <span>get_car</span><span>()</span> <span>{</span><span>return</span> <span>car</span><span>;</span><span>}</span><span>};</span><span>class</span> <span>CarDirector</span> <span>{</span><span>private:</span><span>ICarBuilder</span><span>*</span> <span>builder</span><span>;</span><span>public:</span><span>CarDirector</span><span>(</span><span>ICarBuilder</span><span>*</span> <span>builder</span><span>)</span> <span>{</span><span>this</span><span>-></span><span>builder</span> <span>=</span> <span>builder</span><span>;</span><span>}</span><span>void</span> <span>build_car</span><span>()</span> <span>{</span><span>builder</span><span>-></span><span>add_engine</span><span>(</span><span>"V6"</span><span>);</span><span>builder</span><span>-></span><span>add_doors</span><span>(</span><span>4</span><span>);</span><span>builder</span><span>-></span><span>paint</span><span>(</span><span>"Red"</span><span>);</span><span>}</span><span>};</span><span>int</span> <span>main</span><span>()</span> <span>{</span><span>AudiCarBuilder</span> <span>audiBuilder</span><span>;</span><span>CarDirector</span> <span>director</span><span>(</span><span>&</span><span>audiBuilder</span><span>);</span><span>director</span><span>.</span><span>build_car</span><span>();</span><span>Car</span> <span>audiCar</span> <span>=</span> <span>audiBuilder</span><span>.</span><span>get_car</span><span>();</span><span>std</span><span>::</span><span>cout</span> <span><<</span> <span>"Audi car: "</span><span>;</span><span>audiCar</span><span>.</span><span>display</span><span>();</span><span>return</span> <span>0</span><span>;</span><span>}</span><span>#include</span> <span><iostream></span><span> #include</span> <span><string></span><span> </span> <span>class</span> <span>Car</span> <span>{</span> <span>private:</span> <span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>;</span> <span>int</span> <span>num_doors</span><span>;</span> <span>std</span><span>::</span><span>string</span> <span>color</span><span>;</span> <span>public:</span> <span>void</span> <span>set_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>{</span> <span>this</span><span>-></span><span>engine_type</span> <span>=</span> <span>engine_type</span><span>;</span> <span>}</span> <span>void</span> <span>set_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>{</span> <span>this</span><span>-></span><span>num_doors</span> <span>=</span> <span>num_doors</span><span>;</span> <span>}</span> <span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>{</span> <span>this</span><span>-></span><span>color</span> <span>=</span> <span>color</span><span>;</span> <span>}</span> <span>void</span> <span>display</span><span>()</span> <span>{</span> <span>std</span><span>::</span><span>cout</span> <span><<</span> <span>"Car with "</span> <span><<</span> <span>engine_type</span> <span><<</span> <span>" engine, "</span> <span><<</span> <span>num_doors</span> <span><<</span> <span>" doors, and "</span> <span><<</span> <span>color</span> <span><<</span> <span>" color."</span> <span><<</span> <span>std</span><span>::</span><span>endl</span><span>;</span> <span>}</span> <span>};</span> <span>class</span> <span>ICarBuilder</span> <span>{</span> <span>public:</span> <span>virtual</span> <span>void</span> <span>add_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>=</span> <span>0</span><span>;</span> <span>virtual</span> <span>void</span> <span>add_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>=</span> <span>0</span><span>;</span> <span>virtual</span> <span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>=</span> <span>0</span><span>;</span> <span>virtual</span> <span>Car</span> <span>get_car</span><span>()</span> <span>=</span> <span>0</span><span>;</span> <span>};</span> <span>class</span> <span>AudiCarBuilder</span> <span>:</span> <span>public</span> <span>ICarBuilder</span> <span>{</span> <span>private:</span> <span>Car</span> <span>car</span><span>;</span> <span>public:</span> <span>void</span> <span>add_engine</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>engine_type</span><span>)</span> <span>{</span> <span>car</span><span>.</span><span>set_engine</span><span>(</span><span>engine_type</span><span>);</span> <span>}</span> <span>void</span> <span>add_doors</span><span>(</span><span>int</span> <span>num_doors</span><span>)</span> <span>{</span> <span>car</span><span>.</span><span>set_doors</span><span>(</span><span>num_doors</span><span>);</span> <span>}</span> <span>void</span> <span>paint</span><span>(</span><span>std</span><span>::</span><span>string</span> <span>color</span><span>)</span> <span>{</span> <span>car</span><span>.</span><span>paint</span><span>(</span><span>color</span><span>);</span> <span>}</span> <span>Car</span> <span>get_car</span><span>()</span> <span>{</span> <span>return</span> <span>car</span><span>;</span> <span>}</span> <span>};</span> <span>class</span> <span>CarDirector</span> <span>{</span> <span>private:</span> <span>ICarBuilder</span><span>*</span> <span>builder</span><span>;</span> <span>public:</span> <span>CarDirector</span><span>(</span><span>ICarBuilder</span><span>*</span> <span>builder</span><span>)</span> <span>{</span> <span>this</span><span>-></span><span>builder</span> <span>=</span> <span>builder</span><span>;</span> <span>}</span> <span>void</span> <span>build_car</span><span>()</span> <span>{</span> <span>builder</span><span>-></span><span>add_engine</span><span>(</span><span>"V6"</span><span>);</span> <span>builder</span><span>-></span><span>add_doors</span><span>(</span><span>4</span><span>);</span> <span>builder</span><span>-></span><span>paint</span><span>(</span><span>"Red"</span><span>);</span> <span>}</span> <span>};</span> <span>int</span> <span>main</span><span>()</span> <span>{</span> <span>AudiCarBuilder</span> <span>audiBuilder</span><span>;</span> <span>CarDirector</span> <span>director</span><span>(</span><span>&</span><span>audiBuilder</span><span>);</span> <span>director</span><span>.</span><span>build_car</span><span>();</span> <span>Car</span> <span>audiCar</span> <span>=</span> <span>audiBuilder</span><span>.</span><span>get_car</span><span>();</span> <span>std</span><span>::</span><span>cout</span> <span><<</span> <span>"Audi car: "</span><span>;</span> <span>audiCar</span><span>.</span><span>display</span><span>();</span> <span>return</span> <span>0</span><span>;</span> <span>}</span>#include <iostream> #include <string> class Car { private: std::string engine_type; int num_doors; std::string color; public: void set_engine(std::string engine_type) { this->engine_type = engine_type; } void set_doors(int num_doors) { this->num_doors = num_doors; } void paint(std::string color) { this->color = color; } void display() { std::cout << "Car with " << engine_type << " engine, " << num_doors << " doors, and " << color << " color." << std::endl; } }; class ICarBuilder { public: virtual void add_engine(std::string engine_type) = 0; virtual void add_doors(int num_doors) = 0; virtual void paint(std::string color) = 0; virtual Car get_car() = 0; }; class AudiCarBuilder : public ICarBuilder { private: Car car; public: void add_engine(std::string engine_type) { car.set_engine(engine_type); } void add_doors(int num_doors) { car.set_doors(num_doors); } void paint(std::string color) { car.paint(color); } Car get_car() { return car; } }; class CarDirector { private: ICarBuilder* builder; public: CarDirector(ICarBuilder* builder) { this->builder = builder; } void build_car() { builder->add_engine("V6"); builder->add_doors(4); builder->paint("Red"); } }; int main() { AudiCarBuilder audiBuilder; CarDirector director(&audiBuilder); director.build_car(); Car audiCar = audiBuilder.get_car(); std::cout << "Audi car: "; audiCar.display(); return 0; }
Enter fullscreen mode Exit fullscreen mode
Remember, same way you can also add another car builder, say FordCarBuilder
Conclusion
In conclusion, the Builder pattern is a powerful design pattern that can help us create complex objects with many attributes in a more organized and maintainable way. By separating the construction of an object from its representation, we can create different types of objects with different attributes using the same building process.
Photo by Kelly Sikkema on Unsplash
原文链接:The Power of Builder Design Pattern: How to Create Complex Objects with Ease
暂无评论内容