1//! @file structural.cpp
2//! @author ryftchen
3//! @brief The definitions (structural) in the data structure module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#include "structural.hpp"
8
9#include <algorithm>
10
11namespace design_pattern::structural
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 adapter
22{
23void Adaptee::specificRequest() const // NOLINT(readability-convert-member-functions-to-static)
24{
25 output() << "specific request\n";
26}
27
28void Adapter::request()
29{
30 adaptee->specificRequest();
31}
32
33//! @brief Output stream for the adapter pattern. Need to be cleared manually.
34//! @return reference of the output stream object, which is on string based
35std::ostringstream& output() noexcept
36{
37 static std::ostringstream process{};
38 return process;
39}
40} // namespace adapter
41
42namespace bridge
43{
44void ConcreteImplementorA::action()
45{
46 output() << "concrete implementor A\n";
47}
48
49void ConcreteImplementorB::action()
50{
51 output() << "concrete implementor B\n";
52}
53
54void RefinedAbstraction::operation()
55{
56 implementor->action();
57}
58
59//! @brief Output stream for the bridge pattern. Need to be cleared manually.
60//! @return reference of the output stream object, which is on string based
61std::ostringstream& output() noexcept
62{
63 static std::ostringstream process{};
64 return process;
65}
66} // namespace bridge
67
68namespace composite
69{
70std::shared_ptr<Component> Component::getChild(const std::uint32_t /*index*/)
71{
72 return nullptr;
73}
74
75void Component::add(const std::shared_ptr<Component>& /*component*/)
76{
77}
78
79void Component::remove(const std::uint32_t /*index*/)
80{
81}
82
83std::shared_ptr<Component> Composite::getChild(const std::uint32_t index)
84{
85 return children.at(n: index);
86}
87
88void Composite::add(const std::shared_ptr<Component>& component)
89{
90 children.emplace_back(args: component);
91}
92
93void Composite::remove(const std::uint32_t index)
94{
95 children.erase(position: children.cbegin() + index);
96}
97
98void Composite::operation()
99{
100 std::ranges::for_each(children, [](const auto& component) { component->operation(); });
101}
102
103void Leaf::operation()
104{
105 output() << "leaf " << id << " operation\n";
106}
107
108//! @brief Output stream for the composite pattern. Need to be cleared manually.
109//! @return reference of the output stream object, which is on string based
110std::ostringstream& output() noexcept
111{
112 static std::ostringstream process{};
113 return process;
114}
115} // namespace composite
116
117namespace decorator
118{
119void ConcreteComponent::operation()
120{
121 output() << "concrete component operation\n";
122}
123
124void Decorator::operation()
125{
126 component->operation();
127}
128
129void ConcreteDecoratorA::operation()
130{
131 Decorator::operation();
132 output() << "decorator A\n";
133}
134
135//! @brief The related operation.
136void ConcreteDecoratorB::operation()
137{
138 Decorator::operation();
139 output() << "decorator B\n";
140}
141
142//! @brief Output stream for the decorator pattern. Need to be cleared manually.
143//! @return reference of the output stream object, which is on string based
144std::ostringstream& output() noexcept
145{
146 static std::ostringstream process{};
147 return process;
148}
149} // namespace decorator
150
151namespace facade
152{
153// NOLINTBEGIN(readability-convert-member-functions-to-static)
154void SubsystemA::suboperation() const
155{
156 output() << "subsystem A method\n";
157}
158
159void SubsystemB::suboperation() const
160{
161 output() << "subsystem B method\n";
162}
163
164void SubsystemC::suboperation() const
165{
166 output() << "subsystem C method\n";
167}
168// NOLINTEND(readability-convert-member-functions-to-static)
169
170void Facade::operation1()
171{
172 subsystemA->suboperation();
173 subsystemB->suboperation();
174}
175
176void Facade::operation2()
177{
178 subsystemC->suboperation();
179}
180
181//! @brief Output stream for the facade pattern. Need to be cleared manually.
182//! @return reference of the output stream object, which is on string based
183std::ostringstream& output() noexcept
184{
185 static std::ostringstream process{};
186 return process;
187}
188} // namespace facade
189
190namespace flyweight
191{
192void UnsharedConcreteFlyweight::operation()
193{
194 output() << "unshared flyweight with state " << state << '\n';
195}
196
197void ConcreteFlyweight::operation()
198{
199 output() << "concrete flyweight with state " << state << '\n';
200}
201
202std::unique_ptr<Flyweight>& FlyweightFactory::getFlyweight(const int key)
203{
204 if (flies.contains(x: key))
205 {
206 return flies[key];
207 }
208
209 std::unique_ptr<Flyweight> fly = std::make_unique<ConcreteFlyweight>(args: key);
210 flies.emplace(args: key, args: std::move(fly));
211 return flies[key];
212}
213
214//! @brief Output stream for the flyweight pattern. Need to be cleared manually.
215//! @return reference of the output stream object, which is on string based
216std::ostringstream& output() noexcept
217{
218 static std::ostringstream process{};
219 return process;
220}
221} // namespace flyweight
222
223namespace proxy
224{
225void RealSubject::request()
226{
227 output() << "real subject request\n";
228}
229
230void Proxy::request()
231{
232 realSubject().request();
233}
234
235RealSubject& Proxy::realSubject()
236{
237 if (!subject)
238 {
239 subject = std::make_unique<RealSubject>();
240 }
241 return *subject;
242}
243
244//! @brief Output stream for the proxy pattern. Need to be cleared manually.
245//! @return reference of the output stream object, which is on string based
246std::ostringstream& output() noexcept
247{
248 static std::ostringstream process{};
249 return process;
250}
251} // namespace proxy
252} // namespace design_pattern::structural
253