Skip to content

Commit 1c7f57a

Browse files
authored
Merge pull request #25 from urboob21/dev_branch
id 1764056185
2 parents 937de4f + 114448a commit 1c7f57a

3 files changed

Lines changed: 218 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ set(APP_SOURCES
110110
"src/patterns/behavioral/Observer.cpp"
111111
"src/patterns/creational/Singleton.cpp"
112112
"src/patterns/creational/FactoryMethod.cpp"
113+
"src/patterns/creational/Builder.cpp"
113114
)
114115

115116
# Test files

docs/uml/patterns_creational_builder.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
// cppcheck-suppress-file [functionStatic]
2+
3+
// Builder is a creational design pattern that lets you construct complex objects step by step.
4+
// The pattern allows you to produce different types and representations of an object using the same construction code.
5+
// Appicability:
6+
// (*) Use the Builder pattern to get rid of a “telescoping constructor”.
7+
// (**) when you want your code to be able to create different representations of some product (for example, stone and wooden houses).
8+
9+
// UML: docs/uml/patterns_behavioral_iterator.drawio.svg
10+
11+
#include <iostream>
12+
13+
#include <iostream>
14+
#include <string>
15+
#include <vector>
16+
#include <memory>
17+
18+
namespace
19+
{
20+
namespace BuilderPattern
21+
{
22+
class Product
23+
{
24+
private:
25+
std::vector<std::string> m_parts;
26+
27+
public:
28+
void addPart(const std::string &part)
29+
{
30+
m_parts.push_back(part);
31+
}
32+
33+
void print() const
34+
{
35+
std::cout << "Product parts: ";
36+
for (size_t i = 0; i < m_parts.size(); ++i)
37+
{
38+
std::cout << m_parts[i];
39+
if (i + 1 < m_parts.size())
40+
std::cout << ", ";
41+
}
42+
std::cout << "\n\n";
43+
}
44+
};
45+
46+
/**
47+
* The Builder interface specifies methods for creating the different parts of
48+
* the Product objects.
49+
*/
50+
class IBuilder
51+
{
52+
public:
53+
virtual ~IBuilder() = default;
54+
virtual IBuilder &reset() = 0;
55+
virtual IBuilder &producePart1() = 0;
56+
virtual IBuilder &producePart2() = 0;
57+
virtual IBuilder &producePart3() = 0;
58+
59+
virtual Product *const build() = 0;
60+
};
61+
62+
class AbstractBuilder : public IBuilder
63+
{
64+
protected:
65+
Product *m_product;
66+
67+
public:
68+
explicit AbstractBuilder()
69+
{
70+
m_product = new Product();
71+
}
72+
73+
~AbstractBuilder()
74+
{
75+
delete m_product;
76+
}
77+
78+
AbstractBuilder(const AbstractBuilder &other)
79+
{
80+
if (m_product != nullptr)
81+
{
82+
delete m_product;
83+
}
84+
m_product = new Product();
85+
*m_product = *other.m_product;
86+
}
87+
88+
AbstractBuilder &operator=(const AbstractBuilder &other)
89+
{
90+
if (this == &other)
91+
{
92+
return *this;
93+
}
94+
if (m_product != nullptr)
95+
{
96+
delete m_product;
97+
}
98+
m_product = new Product();
99+
*m_product = *other.m_product;
100+
return *this;
101+
}
102+
103+
IBuilder &reset() override final
104+
{
105+
if (m_product != nullptr)
106+
{
107+
delete m_product;
108+
}
109+
m_product = new Product();
110+
111+
return *this;
112+
}
113+
};
114+
115+
/**
116+
* The Concrete Builder classes follow the Builder interface and provide
117+
* specific implementations of the building steps. Your program may have several
118+
* variations of Builders, implemented differently.
119+
*/
120+
class SimpleBuilder : public AbstractBuilder
121+
{
122+
public:
123+
IBuilder &producePart1() override
124+
{
125+
m_product->addPart("PART1");
126+
return *this;
127+
}
128+
129+
IBuilder &producePart2() override
130+
{
131+
m_product->addPart("PART2");
132+
return *this;
133+
}
134+
135+
IBuilder &producePart3() override
136+
{
137+
m_product->addPart("PART3");
138+
return *this;
139+
}
140+
141+
Product *const build() override
142+
{
143+
return m_product;
144+
}
145+
};
146+
147+
class ComplexBuilder : public AbstractBuilder
148+
{
149+
public:
150+
IBuilder &producePart1() override
151+
{
152+
m_product->addPart("PART_1-X9a7Fq!2@Lm#48Z");
153+
return *this;
154+
}
155+
156+
IBuilder &producePart2() override
157+
{
158+
m_product->addPart("PART_2-X9a7Fq!2@Lm#48Z");
159+
return *this;
160+
}
161+
162+
IBuilder &producePart3() override
163+
{
164+
m_product->addPart("PART_3-X9a7Fq!2@Lm#48Z");
165+
return *this;
166+
}
167+
168+
Product *const build() override
169+
{
170+
return m_product;
171+
}
172+
};
173+
174+
namespace Client
175+
{
176+
void clientCode(IBuilder *const builder)
177+
{
178+
const Product *product1 = (*builder).producePart1().producePart2().producePart3().build();
179+
product1->print();
180+
181+
const Product *product2 = (*builder).reset().producePart1().build();
182+
product2->print();
183+
}
184+
}
185+
186+
void run()
187+
{
188+
{
189+
std::cout << "ConcreteBuilder: Simple\n";
190+
IBuilder *builder = new SimpleBuilder();
191+
Client::clientCode(builder);
192+
delete builder;
193+
}
194+
{
195+
std::cout << "ConcreteBuilder: Complex\n";
196+
IBuilder *builder = new ComplexBuilder();
197+
Client::clientCode(builder);
198+
delete builder;
199+
}
200+
}
201+
}
202+
}
203+
204+
struct BuilderAutoRunner
205+
{
206+
BuilderAutoRunner()
207+
{
208+
std::cout << "\n--- Builder Pattern Example ---\n";
209+
BuilderPattern::run();
210+
}
211+
};
212+
213+
static BuilderAutoRunner instance;

0 commit comments

Comments
 (0)