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-2025 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()
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::for_each(first: children.cbegin(), last: children.cend(), f: [](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{
153void SubsystemA::suboperation()
154{
155 output() << "subsystem A method\n";
156}
157
158void SubsystemB::suboperation()
159{
160 output() << "subsystem B method\n";
161}
162
163void SubsystemC::suboperation()
164{
165 output() << "subsystem C method\n";
166}
167
168void Facade::operation1()
169{
170 subsystemA->suboperation();
171 subsystemB->suboperation();
172}
173
174void Facade::operation2()
175{
176 subsystemC->suboperation();
177}
178
179//! @brief Output stream for the facade pattern. Need to be cleared manually.
180//! @return reference of the output stream object, which is on string based
181std::ostringstream& output() noexcept
182{
183 static std::ostringstream process{};
184 return process;
185}
186} // namespace facade
187
188namespace flyweight
189{
190void UnsharedConcreteFlyweight::operation()
191{
192 output() << "unshared flyweight with state " << state << '\n';
193}
194
195void ConcreteFlyweight::operation()
196{
197 output() << "concrete flyweight with state " << state << '\n';
198}
199
200std::unique_ptr<Flyweight>& FlyweightFactory::getFlyweight(const int key)
201{
202 if (flies.contains(x: key))
203 {
204 return flies[key];
205 }
206
207 std::unique_ptr<Flyweight> fly = std::make_unique<ConcreteFlyweight>(args: key);
208 flies.emplace(args: key, args: std::move(fly));
209 return flies[key];
210}
211
212//! @brief Output stream for the flyweight pattern. Need to be cleared manually.
213//! @return reference of the output stream object, which is on string based
214std::ostringstream& output() noexcept
215{
216 static std::ostringstream process{};
217 return process;
218}
219} // namespace flyweight
220
221namespace proxy
222{
223void RealSubject::request()
224{
225 output() << "real subject request\n";
226}
227
228void Proxy::request()
229{
230 realSubject().request();
231}
232
233RealSubject& Proxy::realSubject()
234{
235 if (!subject)
236 {
237 subject = std::make_unique<RealSubject>();
238 }
239 return *subject;
240}
241
242//! @brief Output stream for the proxy pattern. Need to be cleared manually.
243//! @return reference of the output stream object, which is on string based
244std::ostringstream& output() noexcept
245{
246 static std::ostringstream process{};
247 return process;
248}
249} // namespace proxy
250} // namespace design_pattern::structural
251