Skip to content

Commit 4218cd6

Browse files
committed
翻訳記事追加
1 parent bdd8076 commit 4218cd6

1 file changed

Lines changed: 138 additions & 0 deletions

File tree

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
title: GoF Design Patterns - Builder
3+
date: 2026-02-04
4+
category: Coding
5+
description: A practical guide to the Builder pattern from the GoF collection:concepts, when to use it, a C++ implementation example, caveats, and sources.
6+
tags: [Coding, DesignPattern]
7+
recommended: true
8+
thumbnail: assets/img/ogp.png
9+
---
10+
11+
Hello! Pan here.
12+
13+
This post covers the Builder pattern from the GoF (Gang of Four) design patterns.
14+
I explain it practically with sample code in C++, how to design it, when to apply it, and important caveats.
15+
16+
# Introduction
17+
18+
The Builder pattern separates the construction of a complex object from its representation, improving readability and extensibility of the creation process.
19+
20+
I'll quote Wikipedia as a primary source:
21+
22+
> "The intent of the Builder design pattern is to separate the construction of a complex object from its representation so that the same construction process can create different representations."
23+
> (Source: [https://en.wikipedia.org/wiki/Builder_pattern](https://en.wikipedia.org/wiki/Builder_pattern))
24+
25+
[!CARD](https://en.wikipedia.org/wiki/Builder_pattern)
26+
27+
## Structure (Elements)
28+
29+
A typical composition includes:
30+
31+
- `Product`: the complex object to be constructed
32+
- `Builder`: defines steps like `BuildPartX()` and provides `GetResult()`
33+
- `ConcreteBuilder`: implements `Builder`, holds mutable parts internally, and returns the final `Product`
34+
- `Director`: holds the construction sequence and issues build commands to the `Builder`. For small cases, the Director is often omitted.
35+
36+
## C++ Implementation Example
37+
38+
Below is a minimal C++ example. This is a typical pattern that uses a `Director`.
39+
40+
```cpp
41+
// Product.h -- the object being constructed
42+
#pragma once
43+
#include <string>
44+
45+
struct Product {
46+
std::string partA;
47+
std::string partB;
48+
std::string partC;
49+
};
50+
51+
// Builder.h -- abstract builder
52+
#pragma once
53+
#include <memory>
54+
55+
class Builder {
56+
public:
57+
virtual ~Builder() = default;
58+
virtual void BuildPartA() = 0;
59+
virtual void BuildPartB() = 0;
60+
virtual void BuildPartC() = 0;
61+
virtual std::unique_ptr<Product> GetResult() = 0;
62+
};
63+
64+
// ConcreteBuilder.h
65+
#pragma once
66+
#include "Builder.h"
67+
#include "Product.h"
68+
#include <memory>
69+
70+
class ConcreteBuilder : public Builder {
71+
private:
72+
std::unique_ptr<Product> product_;
73+
public:
74+
ConcreteBuilder() : product_(std::make_unique<Product>()) {}
75+
void BuildPartA() override { product_->partA = "Engine"; }
76+
void BuildPartB() override { product_->partB = "Wheels"; }
77+
void BuildPartC() override { product_->partC = "Body"; }
78+
std::unique_ptr<Product> GetResult() override {
79+
return std::move(product_);
80+
}
81+
};
82+
83+
// Director.h
84+
#pragma once
85+
#include "Builder.h"
86+
87+
class Director {
88+
public:
89+
void ConstructSportsCar(Builder& builder) {
90+
builder.BuildPartA();
91+
builder.BuildPartB();
92+
builder.BuildPartC();
93+
}
94+
void ConstructToyCar(Builder& builder) {
95+
builder.BuildPartB();
96+
// Toy car doesn't need engine
97+
}
98+
};
99+
100+
// main.cpp
101+
#include <iostream>
102+
int main() {
103+
ConcreteBuilder builder;
104+
Director director;
105+
director.ConstructSportsCar(builder);
106+
auto product = builder.GetResult();
107+
std::cout << "Product parts: " << product->partA << ", " << product->partB << ", " << product->partC << "\n";
108+
}
109+
```
110+
111+
The key point of this implementation is the separation between the construction procedure (the Director) and the concrete construction steps (the ConcreteBuilder). You can achieve variety simply by replacing `ConcreteBuilder`.
112+
113+
## When to Use It
114+
115+
Representative cases where you should consider the Builder pattern:
116+
117+
- When a constructor has many parameters and most of them are optional (named/optional parameters or factories can be alternatives).
118+
- When you need staged or complex initialization and want to separate the initialization steps (useful for incremental verification in tests).
119+
- When you want to produce different representations from the same construction procedure (multiple `ConcreteBuilder` implementations).
120+
- When building immutable objects: the Builder assembles a mutable intermediate representation and returns an immutable object at the end for readability.
121+
122+
Alternatives:
123+
124+
- Language-level named/optional parameters (for concise cases).
125+
- `Factory Method` or `Abstract Factory` (when creation responsibilities are managed by subclasses or family groups).
126+
- Stepwise helper functions calling constructors (often sufficient for simple cases).
127+
128+
## Summary
129+
130+
The Builder pattern is a powerful pattern intended to separate construction procedure and representation. It is effective when dealing with complex initialization or variable representations. However, Builder introduces trade-offs around mutability, integration with dependency injection, and test design. Before adopting it, evaluate the impact on creation sites, serialization, and tests.
131+
132+
References and sources:
133+
134+
[!CARD](https://en.wikipedia.org/wiki/Builder_pattern)
135+
136+
That's it for this post. Next time I'll cover another GoF pattern. The code shown here is simplified for learning purposes — when adopting patterns in production, make sure to adapt them to your project requirements.
137+
138+
Thanks for reading — Pan.

0 commit comments

Comments
 (0)