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