1//! @file creational.hpp
2//! @author ryftchen
3//! @brief The declarations (creational) in the design pattern module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2025 ryftchen. All rights reserved.
6
7#pragma once
8
9#include <memory>
10#include <sstream>
11
12//! @brief The design pattern module.
13namespace design_pattern // NOLINT(modernize-concat-nested-namespaces)
14{
15//! @brief Creational-related functions in the design pattern module.
16namespace creational
17{
18//! @brief Brief function description.
19//! @return function description (module_function)
20inline static const char* description() noexcept
21{
22 return "DP_CREATIONAL";
23}
24extern const char* version() noexcept;
25
26//! @brief The abstract factory pattern.
27namespace abstract_factory
28{
29//! @brief Implement the same interface. The others can refer to the interface not the concrete product.
30class ProductA
31{
32public:
33 //! @brief Construct a new ProductA object.
34 ProductA() = default;
35 //! @brief Destroy the ProductA object.
36 virtual ~ProductA() = default;
37 //! @brief Construct a new ProductA object.
38 ProductA(const ProductA&) = default;
39 //! @brief Construct a new ProductA object.
40 ProductA(ProductA&&) noexcept = default;
41 //! @brief The operator (=) overloading of ProductA class.
42 //! @return reference of the ProductA object
43 ProductA& operator=(const ProductA&) = default;
44 //! @brief The operator (=) overloading of ProductA class.
45 //! @return reference of the ProductA object
46 ProductA& operator=(ProductA&&) noexcept = default;
47
48 //! @brief Get the product name.
49 //! @return product name
50 [[nodiscard]] virtual std::string getName() const = 0;
51};
52
53//! @brief The concrete product.
54class ConcreteProductAX : public ProductA
55{
56public:
57 //! @brief Get the product name.
58 //! @return product name
59 [[nodiscard]] std::string getName() const override;
60};
61
62//! @brief The concrete product.
63class ConcreteProductAY : public ProductA
64{
65public:
66 //! @brief Get the product name.
67 //! @return product name
68 [[nodiscard]] std::string getName() const override;
69};
70
71//! @brief Implement the same interface. The others can refer to the interface not the concrete product.
72class ProductB
73{
74public:
75 //! @brief Construct a new ProductB object.
76 ProductB() = default;
77 //! @brief Destroy the ProductB object.
78 virtual ~ProductB() = default;
79 //! @brief Construct a new ProductB object.
80 ProductB(const ProductB&) = default;
81 //! @brief Construct a new ProductB object.
82 ProductB(ProductB&&) noexcept = default;
83 //! @brief The operator (=) overloading of ProductB class.
84 //! @return reference of the ProductB object
85 ProductB& operator=(const ProductB&) = default;
86 //! @brief The operator (=) overloading of ProductB class.
87 //! @return reference of the ProductB object
88 ProductB& operator=(ProductB&&) noexcept = default;
89
90 //! @brief Get the product name.
91 //! @return product name
92 [[nodiscard]] virtual std::string getName() const = 0;
93};
94
95//! @brief The concrete product.
96class ConcreteProductBX : public ProductB
97{
98public:
99 //! @brief Get the product name.
100 //! @return product name
101 [[nodiscard]] std::string getName() const override;
102};
103
104//! @brief The concrete product.
105class ConcreteProductBY : public ProductB
106{
107public:
108 //! @brief Get the product name.
109 //! @return product name
110 [[nodiscard]] std::string getName() const override;
111};
112
113//! @brief Provide the abstract interface for creating the family of products.
114//! It never has to instantiate a product object.
115class AbstractFactory
116{
117public:
118 //! @brief Construct a new AbstractFactory object.
119 AbstractFactory() = default;
120 //! @brief Destroy the AbstractFactory object.
121 virtual ~AbstractFactory() = default;
122 //! @brief Construct a new AbstractFactory object.
123 AbstractFactory(const AbstractFactory&) = default;
124 //! @brief Construct a new AbstractFactory object.
125 AbstractFactory(AbstractFactory&&) noexcept = default;
126 //! @brief The operator (=) overloading of AbstractFactory class.
127 //! @return reference of the AbstractFactory object
128 AbstractFactory& operator=(const AbstractFactory&) = default;
129 //! @brief The operator (=) overloading of AbstractFactory class.
130 //! @return reference of the AbstractFactory object
131 AbstractFactory& operator=(AbstractFactory&&) noexcept = default;
132
133 //! @brief Create product A.
134 //! @return product A
135 virtual std::unique_ptr<ProductA> createProductA() = 0;
136 //! @brief Create product B.
137 //! @return product B
138 virtual std::unique_ptr<ProductB> createProductB() = 0;
139};
140
141//! @brief The concrete factory.
142class ConcreteFactoryX : public AbstractFactory
143{
144public:
145 //! @brief Create product A.
146 //! @return product A
147 std::unique_ptr<ProductA> createProductA() override;
148 //! @brief Create product B.
149 //! @return product B
150 std::unique_ptr<ProductB> createProductB() override;
151};
152
153//! @brief The concrete factory.
154class ConcreteFactoryY : public AbstractFactory
155{
156public:
157 //! @brief Create product A.
158 //! @return product A
159 std::unique_ptr<ProductA> createProductA() override;
160 //! @brief Create product B.
161 //! @return product B
162 std::unique_ptr<ProductB> createProductB() override;
163};
164
165extern std::ostringstream& output() noexcept;
166} // namespace abstract_factory
167
168//! @brief The builder pattern.
169namespace builder
170{
171//! @brief Product properties.
172class Product
173{
174public:
175 //! @brief Make part A.
176 //! @param part - target part
177 void makeA(const std::string_view part);
178 //! @brief Make part B.
179 //! @param part - target part
180 void makeB(const std::string_view part);
181 //! @brief Make part C.
182 //! @param part - target part
183 void makeC(const std::string_view part);
184 //! @brief Get all parts.
185 //! @return all parts
186 [[nodiscard]] std::string get() const;
187
188private:
189 //! @brief Part A.
190 std::string partA;
191 //! @brief Part B.
192 std::string partB;
193 //! @brief Part C.
194 std::string partC;
195};
196
197//! @brief The builder for creating products.
198class Builder
199{
200public:
201 //! @brief Construct a new Builder object.
202 Builder() = default;
203 //! @brief Destroy the Builder object.
204 virtual ~Builder() = default;
205 //! @brief Construct a new Builder object.
206 Builder(const Builder&) = default;
207 //! @brief Construct a new Builder object.
208 Builder(Builder&&) noexcept = default;
209 //! @brief The operator (=) overloading of Builder class.
210 //! @return reference of the Builder object
211 Builder& operator=(const Builder&) = delete;
212 //! @brief The operator (=) overloading of Builder class.
213 //! @return reference of the Builder object
214 Builder& operator=(Builder&&) noexcept = delete;
215
216 //! @brief Get the product.
217 //! @return product
218 [[nodiscard]] Product get() const;
219 //! @brief Build part A.
220 virtual void buildPartA() = 0;
221 //! @brief Build part B.
222 virtual void buildPartB() = 0;
223 //! @brief Build part C.
224 virtual void buildPartC() = 0;
225
226protected:
227 //! @brief The product.
228 Product product{};
229};
230
231//! @brief The concrete builder.
232class ConcreteBuilderX : public Builder
233{
234public:
235 //! @brief Build part A.
236 void buildPartA() override;
237 //! @brief Build part B.
238 void buildPartB() override;
239 //! @brief Build part C.
240 void buildPartC() override;
241};
242
243//! @brief The concrete builder.
244class ConcreteBuilderY : public Builder
245{
246public:
247 //! @brief Build part A.
248 void buildPartA() override;
249 //! @brief Build part B.
250 void buildPartB() override;
251 //! @brief Build part C.
252 void buildPartC() override;
253};
254
255//! @brief Manage the correct sequence of creation.
256class Director
257{
258public:
259 //! @brief Set the builder.
260 //! @param b - target builder
261 void set(std::unique_ptr<Builder> b);
262 //! @brief Get the product from the builder.
263 //! @return product
264 [[nodiscard]] Product get() const;
265 //! @brief Construct products by the builder.
266 void construct();
267
268private:
269 //! @brief The builder.
270 std::unique_ptr<Builder> builder;
271};
272
273extern std::ostringstream& output() noexcept;
274} // namespace builder
275
276//! @brief The factory method pattern.
277namespace factory_method
278{
279//! @brief Implement the same interface. The others can refer to the interface not the concrete product.
280class Product
281{
282public:
283 //! @brief Construct a new Product object.
284 Product() = default;
285 //! @brief Destroy the Product object.
286 virtual ~Product() = default;
287 //! @brief Construct a new Product object.
288 Product(const Product&) = default;
289 //! @brief Construct a new Product object.
290 Product(Product&&) noexcept = default;
291 //! @brief The operator (=) overloading of Product class.
292 //! @return reference of the Product object
293 Product& operator=(const Product&) = default;
294 //! @brief The operator (=) overloading of Product class.
295 //! @return reference of the Product object
296 Product& operator=(Product&&) noexcept = default;
297
298 //! @brief Get the product name.
299 //! @return product name
300 [[nodiscard]] virtual std::string getName() const = 0;
301};
302
303//! @brief The concrete product.
304class ConcreteProductA : public Product
305{
306public:
307 //! @brief Get the product name.
308 //! @return product name
309 [[nodiscard]] std::string getName() const override;
310};
311
312//! @brief The concrete product.
313class ConcreteProductB : public Product
314{
315public:
316 //! @brief Get the product name.
317 //! @return product name
318 [[nodiscard]] std::string getName() const override;
319};
320
321//! @brief Contain the implementation for all methods to manipulate products except for the factory method.
322//! Know how to create the products.
323class Creator
324{
325public:
326 //! @brief Construct a new Creator object.
327 Creator() = default;
328 //! @brief Destroy the Creator object.
329 virtual ~Creator() = default;
330 //! @brief Construct a new Creator object.
331 Creator(const Creator&) = default;
332 //! @brief Construct a new Creator object.
333 Creator(Creator&&) noexcept = default;
334 //! @brief The operator (=) overloading of Creator class.
335 //! @return reference of the Creator object
336 Creator& operator=(const Creator&) = default;
337 //! @brief The operator (=) overloading of Creator class.
338 //! @return reference of the Creator object
339 Creator& operator=(Creator&&) noexcept = default;
340
341 //! @brief Create product A.
342 //! @return product A
343 virtual std::unique_ptr<Product> createProductA() = 0;
344 //! @brief Create product B.
345 //! @return product B
346 virtual std::unique_ptr<Product> createProductB() = 0;
347 //! @brief Remove product.
348 virtual void removeProduct(std::unique_ptr<Product>& product) = 0;
349};
350
351//! @brief The concrete creator.
352class ConcreteCreator : public Creator
353{
354public:
355 //! @brief Create product A.
356 //! @return product A
357 std::unique_ptr<Product> createProductA() override;
358 //! @brief Create product B.
359 //! @return product B
360 std::unique_ptr<Product> createProductB() override;
361 //! @brief Remove product.
362 void removeProduct(std::unique_ptr<Product>& product) override;
363};
364
365extern std::ostringstream& output() noexcept;
366} // namespace factory_method
367
368//! @brief The prototype pattern.
369namespace prototype
370{
371//! @brief The interface for cloning itself.
372class Prototype
373{
374public:
375 //! @brief Construct a new Prototype object.
376 Prototype() = default;
377 //! @brief Destroy the Prototype object.
378 virtual ~Prototype() = default;
379 //! @brief Construct a new Prototype object.
380 Prototype(const Prototype&) = default;
381 //! @brief Construct a new Prototype object.
382 Prototype(Prototype&&) noexcept = default;
383 //! @brief The operator (=) overloading of Prototype class.
384 //! @return reference of the Prototype object
385 Prototype& operator=(const Prototype&) = default;
386 //! @brief The operator (=) overloading of Prototype class.
387 //! @return reference of the Prototype object
388 Prototype& operator=(Prototype&&) noexcept = default;
389
390 //! @brief Clone self.
391 //! @return cloning of self
392 virtual std::unique_ptr<Prototype> clone() = 0;
393 //! @brief Get the type.
394 //! @return type
395 [[nodiscard]] virtual std::string type() const = 0;
396};
397
398//! @brief The concrete prototype.
399class ConcretePrototypeA : public Prototype
400{
401public:
402 //! @brief Clone self.
403 //! @return cloning of self
404 std::unique_ptr<Prototype> clone() override;
405 //! @brief Get the type.
406 //! @return type
407 [[nodiscard]] std::string type() const override;
408};
409
410//! @brief The concrete prototype.
411class ConcretePrototypeB : public Prototype
412{
413public:
414 //! @brief Clone self.
415 //! @return cloning of self
416 std::unique_ptr<Prototype> clone() override;
417 //! @brief Get the type.
418 //! @return type
419 [[nodiscard]] std::string type() const override;
420};
421
422//! @brief Create by asking the prototype to clone itself.
423class Client
424{
425public:
426 //! @brief Initialize all prototypes.
427 static void init();
428 //! @brief Remove all prototypes.
429 static void remove();
430 //! @brief Make by prototype index.
431 //! @param index - prototype index
432 //! @return cloning result
433 static std::unique_ptr<Prototype> make(const int index);
434
435private:
436 //! @brief Collection of prototypes.
437 static std::unique_ptr<Prototype> types[2];
438 //! @brief Number of types.
439 static const int nTypes;
440};
441
442extern std::ostringstream& output() noexcept;
443} // namespace prototype
444
445//! @brief The singleton factory pattern.
446namespace singleton
447{
448//! @brief Have a private static variable to hold one instance of the singleton.
449//! It gives a way to instantiate the singleton.
450class Singleton
451{
452public:
453 //! @brief Destroy the Memento object.
454 virtual ~Singleton() = default;
455 //! @brief Construct a new Singleton object.
456 Singleton(const Singleton&) = delete;
457 //! @brief Construct a new Singleton object.
458 Singleton(Singleton&&) = delete;
459 //! @brief The operator (=) overloading of Singleton class.
460 //! @return reference of the Singleton object
461 Singleton& operator=(const Singleton&) = delete;
462 //! @brief The operator (=) overloading of Singleton class.
463 //! @return reference of the Singleton object
464 Singleton& operator=(Singleton&&) = delete;
465
466 //! @brief Get the instance of the singleton.
467 //! @return instance of the singleton
468 static std::shared_ptr<Singleton> get();
469 //! @brief Restart the instance of the singleton.
470 static void restart();
471 //! @brief Tell external.
472 static void tell();
473
474private:
475 //! @brief Construct a new Singleton object.
476 Singleton() = default;
477
478 //! @brief The instance of the singleton.
479 static std::shared_ptr<Singleton> instance;
480};
481
482extern std::ostringstream& output() noexcept;
483} // namespace singleton
484} // namespace creational
485} // namespace design_pattern
486