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