1//! @file creational.cpp
2//! @author ryftchen
3//! @brief The definitions (creational) in the data structure module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#include "creational.hpp"
8
9#include <algorithm>
10
11namespace design_pattern::creational
12{
13//! @brief Function version number.
14//! @return version number (major.minor.patch)
15const char* version() noexcept
16{
17 static const char* const ver = "0.1.0";
18 return ver;
19}
20
21namespace abstract_factory
22{
23std::string ConcreteProductAX::getName() const
24{
25 return "A-X";
26}
27
28std::string ConcreteProductAY::getName() const
29{
30 return "A-Y";
31}
32
33std::string ConcreteProductBX::getName() const
34{
35 return "B-X";
36}
37
38std::string ConcreteProductBY::getName() const
39{
40 return "B-Y";
41}
42
43std::unique_ptr<ProductA> ConcreteFactoryX::createProductA()
44{
45 return std::make_unique<ConcreteProductAX>();
46}
47
48std::unique_ptr<ProductB> ConcreteFactoryX::createProductB()
49{
50 return std::make_unique<ConcreteProductBX>();
51}
52
53std::unique_ptr<ProductA> ConcreteFactoryY::createProductA()
54{
55 return std::make_unique<ConcreteProductAY>();
56}
57
58std::unique_ptr<ProductB> ConcreteFactoryY::createProductB()
59{
60 return std::make_unique<ConcreteProductBY>();
61}
62
63//! @brief Output stream for the abstract factory pattern. Need to be cleared manually.
64//! @return reference of the output stream object, which is on string based
65std::ostringstream& output() noexcept
66{
67 static std::ostringstream process{};
68 return process;
69}
70} // namespace abstract_factory
71
72namespace builder
73{
74void Product::makeA(const std::string_view part)
75{
76 partA = part;
77}
78
79void Product::makeB(const std::string_view part)
80{
81 partB = part;
82}
83
84void Product::makeC(const std::string_view part)
85{
86 partC = part;
87}
88
89std::string Product::get() const
90{
91 return partA + ' ' + partB + ' ' + partC;
92}
93
94Product Builder::get() const
95{
96 return product;
97}
98
99void ConcreteBuilderX::buildPartA()
100{
101 product.makeA(part: "A-X");
102}
103
104void ConcreteBuilderX::buildPartB()
105{
106 product.makeB(part: "B-X");
107}
108
109void ConcreteBuilderX::buildPartC()
110{
111 product.makeC(part: "C-X");
112}
113
114void ConcreteBuilderY::buildPartA()
115{
116 product.makeA(part: "A-Y");
117}
118
119void ConcreteBuilderY::buildPartB()
120{
121 product.makeB(part: "B-Y");
122}
123
124void ConcreteBuilderY::buildPartC()
125{
126 product.makeC(part: "C-Y");
127}
128
129void Director::set(std::unique_ptr<Builder> b)
130{
131 builder = std::move(b);
132}
133
134Product Director::get() const
135{
136 return builder->get();
137}
138
139void Director::construct()
140{
141 builder->buildPartA();
142 builder->buildPartB();
143 builder->buildPartC();
144}
145
146//! @brief Output stream for the builder pattern. Need to be cleared manually.
147//! @return reference of the output stream object, which is on string based
148std::ostringstream& output() noexcept
149{
150 static std::ostringstream process{};
151 return process;
152}
153} // namespace builder
154
155namespace factory_method
156{
157std::string ConcreteProductA::getName() const
158{
159 return "type A";
160}
161
162std::string ConcreteProductB::getName() const
163{
164 return "type B";
165}
166
167std::unique_ptr<Product> ConcreteCreator::createProductA()
168{
169 return std::make_unique<ConcreteProductA>();
170}
171
172std::unique_ptr<Product> ConcreteCreator::createProductB()
173{
174 return std::make_unique<ConcreteProductB>();
175}
176
177void ConcreteCreator::removeProduct(std::unique_ptr<Product>& product)
178{
179 product.reset();
180}
181
182//! @brief Output stream for the factory method pattern. Need to be cleared manually.
183//! @return reference of the output stream object, which is on string based
184std::ostringstream& output() noexcept
185{
186 static std::ostringstream process{};
187 return process;
188}
189} // namespace factory_method
190
191namespace prototype
192{
193std::array<std::unique_ptr<Prototype>, 2> Client::types = {};
194const int Client::nTypes = 2;
195
196std::unique_ptr<Prototype> ConcretePrototypeA::clone()
197{
198 return std::make_unique<ConcretePrototypeA>();
199}
200
201std::string ConcretePrototypeA::type() const
202{
203 return "type A";
204}
205
206std::unique_ptr<Prototype> ConcretePrototypeB::clone()
207{
208 return std::make_unique<ConcretePrototypeB>();
209}
210
211std::string ConcretePrototypeB::type() const
212{
213 return "type B";
214}
215
216void Client::init()
217{
218 types[0] = std::make_unique<ConcretePrototypeA>();
219 types[1] = std::make_unique<ConcretePrototypeB>();
220}
221
222void Client::remove()
223{
224 std::ranges::for_each(types, [](auto& type) { type.reset(); });
225}
226
227std::unique_ptr<Prototype> Client::make(const int index)
228{
229 return ((index >= 0) && (index < nTypes) && types[index]) ? types[index]->clone() : nullptr;
230}
231
232//! @brief Output stream for the prototype pattern. Need to be cleared manually.
233//! @return reference of the output stream object, which is on string based
234std::ostringstream& output() noexcept
235{
236 static std::ostringstream process{};
237 return process;
238}
239} // namespace prototype
240
241namespace singleton
242{
243std::shared_ptr<Singleton> Singleton::instance = {};
244
245std::shared_ptr<Singleton> Singleton::get()
246{
247 if (!instance)
248 {
249 instance = std::shared_ptr<Singleton>(::new Singleton{});
250 }
251 return instance;
252}
253
254void Singleton::restart()
255{
256 instance.reset();
257}
258
259void Singleton::tell() const // NOLINT(readability-convert-member-functions-to-static)
260{
261 output() << "this is singleton\n";
262}
263
264//! @brief Output stream for the singleton pattern. Need to be cleared manually.
265//! @return reference of the output stream object, which is on string based
266std::ostringstream& output() noexcept
267{
268 static std::ostringstream process{};
269 return process;
270}
271} // namespace singleton
272} // namespace design_pattern::creational
273