1//! @file structural.hpp
2//! @author ryftchen
3//! @brief The declarations (structural) 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 <map>
10#include <memory>
11#include <sstream>
12#include <vector>
13
14//! @brief The design pattern module.
15namespace design_pattern // NOLINT(modernize-concat-nested-namespaces)
16{
17//! @brief Structural-related functions in the design pattern module.
18namespace structural
19{
20//! @brief Brief function description.
21//! @return function description (module_function)
22inline static const char* description() noexcept
23{
24 return "DP_STRUCTURAL";
25}
26extern const char* version() noexcept;
27
28//! @brief The adapter pattern.
29namespace adapter
30{
31//! @brief The specific interface that the client uses.
32class Target
33{
34public:
35 //! @brief Construct a new Target object.
36 Target() = default;
37 //! @brief Destroy the Target object.
38 virtual ~Target() = default;
39 //! @brief Construct a new Target object.
40 Target(const Target&) = default;
41 //! @brief Construct a new Target object.
42 Target(Target&&) noexcept = default;
43 //! @brief The operator (=) overloading of Target class.
44 //! @return reference of the Target object
45 Target& operator=(const Target&) = default;
46 //! @brief The operator (=) overloading of Target class.
47 //! @return reference of the Target object
48 Target& operator=(Target&&) noexcept = default;
49
50 //! @brief Generate a request.
51 virtual void request() = 0;
52};
53
54//! @brief Get calls that client makes on the target because of the adapter.
55class Adaptee
56{
57public:
58 //! @brief The specific request.
59 static void specificRequest();
60};
61
62//! @brief Delegate the call to an adaptee when getting a method call.
63class Adapter : public Target
64{
65public:
66 //! @brief Construct a new Adapter object.
67 Adapter() : adaptee{std::make_unique<Adaptee>()} {}
68
69 //! @brief Generate a request.
70 void request() override;
71
72private:
73 //! @brief The adaptee.
74 std::unique_ptr<Adaptee> adaptee;
75};
76
77extern std::ostringstream& output() noexcept;
78} // namespace adapter
79
80//! @brief The bridge pattern.
81namespace bridge
82{
83//! @brief The interface for implementation.
84class Implementor
85{
86public:
87 //! @brief Construct a new Implementor object.
88 Implementor() = default;
89 //! @brief Destroy the Implementor object.
90 virtual ~Implementor() = default;
91 //! @brief Construct a new Implementor object.
92 Implementor(const Implementor&) = default;
93 //! @brief Construct a new Implementor object.
94 Implementor(Implementor&&) noexcept = default;
95 //! @brief The operator (=) overloading of Implementor class.
96 //! @return reference of the Implementor object
97 Implementor& operator=(const Implementor&) = default;
98 //! @brief The operator (=) overloading of Implementor class.
99 //! @return reference of the Implementor object
100 Implementor& operator=(Implementor&&) noexcept = default;
101
102 //! @brief Implemented action.
103 virtual void action() = 0;
104};
105
106//! @brief The concrete implementor.
107class ConcreteImplementorA : public Implementor
108{
109public:
110 //! @brief Implemented action.
111 void action() override;
112};
113
114//! @brief The concrete implementor.
115class ConcreteImplementorB : public Implementor
116{
117public:
118 //! @brief Implemented action.
119 void action() override;
120};
121
122//! @brief The interface for abstraction.
123class Abstraction
124{
125public:
126 //! @brief Construct a new Abstraction object.
127 Abstraction() = default;
128 //! @brief Destroy the Abstraction object.
129 virtual ~Abstraction() = default;
130 //! @brief Construct a new Abstraction object.
131 Abstraction(const Abstraction&) = default;
132 //! @brief Construct a new Abstraction object.
133 Abstraction(Abstraction&&) noexcept = default;
134 //! @brief The operator (=) overloading of Abstraction class.
135 //! @return reference of the Abstraction object
136 Abstraction& operator=(const Abstraction&) = default;
137 //! @brief The operator (=) overloading of Abstraction class.
138 //! @return reference of the Abstraction object
139 Abstraction& operator=(Abstraction&&) noexcept = default;
140
141 //! @brief Abstracted operation.
142 virtual void operation() = 0;
143};
144
145//! @brief Extend abstraction’s interface.
146class RefinedAbstraction : public Abstraction
147{
148public:
149 //! @brief Construct a new RefinedAbstraction object.
150 //! @param implementor - target implementor
151 explicit RefinedAbstraction(std::unique_ptr<Implementor> implementor) : implementor{std::move(implementor)} {}
152
153 //! @brief Abstracted operation.
154 void operation() override;
155
156private:
157 //! @brief The implementor.
158 const std::unique_ptr<Implementor> implementor;
159};
160
161extern std::ostringstream& output() noexcept;
162} // namespace bridge
163
164//! @brief The composite pattern.
165namespace composite
166{
167//! @brief Both the composite and the leaf nodes are in the composition.
168class Component
169{
170public:
171 //! @brief Construct a new Component object.
172 Component() = default;
173 //! @brief Destroy the Component object.
174 virtual ~Component() = default;
175 //! @brief Construct a new Component object.
176 Component(const Component&) = default;
177 //! @brief Construct a new Component object.
178 Component(Component&&) noexcept = default;
179 //! @brief The operator (=) overloading of Component class.
180 //! @return reference of the Component object
181 Component& operator=(const Component&) = default;
182 //! @brief The operator (=) overloading of Component class.
183 //! @return reference of the Component object
184 Component& operator=(Component&&) noexcept = default;
185
186 //! @brief Get the child component by index.
187 //! @param index - child component index
188 virtual std::shared_ptr<Component> getChild(const std::uint32_t index);
189 //! @brief Add the child component.
190 //! @param component - child component to be added
191 virtual void add(const std::shared_ptr<Component>& component);
192 //! @brief Remove the child component by index.
193 //! @param index - child component index
194 virtual void remove(const std::uint32_t index);
195 //! @brief Execute all child components' operations.
196 virtual void operation() = 0;
197};
198
199//! @brief The behavior of the components having children.
200class Composite : public Component
201{
202public:
203 //! @brief Get the child component by index.
204 //! @param index - child component index
205 //! @return child component
206 std::shared_ptr<Component> getChild(const std::uint32_t index) override;
207 //! @brief Add the child component.
208 //! @param component - child component to be added
209 void add(const std::shared_ptr<Component>& component) override;
210 //! @brief Remove the child component by index.
211 //! @param index - child component index
212 void remove(const std::uint32_t index) override;
213 //! @brief Execute operation.
214 void operation() override;
215
216private:
217 //! @brief Child components.
218 std::vector<std::shared_ptr<Component>> children;
219};
220
221//! @brief The behavior of the element that has no child in the composition.
222class Leaf : public Component
223{
224public:
225 //! @brief Construct a new Leaf object.
226 //! @param id - target leaf node id
227 explicit Leaf(const int id) : id{id} {}
228
229 //! @brief Execute operation.
230 void operation() override;
231
232private:
233 //! @brief Leaf node id.
234 const int id{0};
235};
236
237extern std::ostringstream& output() noexcept;
238} // namespace composite
239
240//! @brief The decorator pattern.
241namespace decorator
242{
243//! @brief The component to which additional responsibilities can be attached.
244class Component
245{
246public:
247 //! @brief Construct a new Component object.
248 Component() = default;
249 //! @brief Destroy the Component object.
250 virtual ~Component() = default;
251 //! @brief Construct a new Component object.
252 Component(const Component&) = default;
253 //! @brief Construct a new Component object.
254 Component(Component&&) noexcept = default;
255 //! @brief The operator (=) overloading of Component class.
256 //! @return reference of the Component object
257 Component& operator=(const Component&) = default;
258 //! @brief The operator (=) overloading of Component class.
259 //! @return reference of the Component object
260 Component& operator=(Component&&) noexcept = default;
261
262 //! @brief The related operation.
263 virtual void operation() = 0;
264};
265
266//! @brief The concrete component.
267class ConcreteComponent : public Component
268{
269public:
270 //! @brief The related operation.
271 void operation() override;
272};
273
274//! @brief Reference to the component. Add responsibilities to the component.
275class Decorator : public Component
276{
277public:
278 //! @brief Construct a new Decorator object.
279 //! @param component - target component
280 explicit Decorator(std::shared_ptr<Component> component) : component{std::move(component)} {}
281
282 //! @brief The related operation.
283 void operation() override;
284
285private:
286 //! @brief The component.
287 const std::shared_ptr<Component> component;
288};
289
290//! @brief The concrete decorator.
291class ConcreteDecoratorA : public Decorator
292{
293public:
294 //! @brief Construct a new ConcreteDecoratorA object.
295 //! @param decorator - target decorator
296 explicit ConcreteDecoratorA(std::shared_ptr<Component> decorator) : Decorator(std::move(decorator)) {}
297
298 //! @brief The related operation.
299 void operation() override;
300};
301
302//! @brief The concrete decorator.
303class ConcreteDecoratorB : public Decorator
304{
305public:
306 //! @brief Construct a new ConcreteDecoratorB object.
307 //! @param decorator - target decorator
308 explicit ConcreteDecoratorB(std::shared_ptr<Component> decorator) : Decorator(std::move(decorator)) {}
309
310 //! @brief The related operation.
311 void operation() override;
312};
313
314extern std::ostringstream& output() noexcept;
315} // namespace decorator
316
317//! @brief The facade pattern.
318namespace facade
319{
320//! @brief Implement complex subsystem functionality.
321class SubsystemA
322{
323public:
324 //! @brief The sub-operation.
325 static void suboperation();
326};
327
328//! @brief Implement complex subsystem functionality.
329class SubsystemB
330{
331public:
332 //! @brief The sub-operation.
333 static void suboperation();
334};
335
336//! @brief Implement complex subsystem functionality.
337class SubsystemC
338{
339public:
340 //! @brief The sub-operation.
341 static void suboperation();
342};
343
344//! @brief Delegate client requests to appropriate subsystem and unified interface.
345class Facade
346{
347public:
348 //! @brief The operation 1.
349 void operation1();
350 //! @brief The operation 2.
351 void operation2();
352
353private:
354 //! @brief Subsystem A.
355 const std::shared_ptr<SubsystemA> subsystemA;
356 //! @brief Subsystem B.
357 const std::shared_ptr<SubsystemB> subsystemB;
358 //! @brief Subsystem C.
359 const std::shared_ptr<SubsystemC> subsystemC;
360};
361
362extern std::ostringstream& output() noexcept;
363} // namespace facade
364
365//! @brief The flyweight pattern.
366namespace flyweight
367{
368//! @brief Receive and act on the extrinsic state through which flyweights.
369class Flyweight
370{
371public:
372 //! @brief Construct a new Flyweight object.
373 Flyweight() = default;
374 //! @brief Destroy the Flyweight object.
375 virtual ~Flyweight() = default;
376 //! @brief Construct a new Flyweight object.
377 Flyweight(const Flyweight&) = default;
378 //! @brief Construct a new Flyweight object.
379 Flyweight(Flyweight&&) noexcept = default;
380 //! @brief The operator (=) overloading of Flyweight class.
381 //! @return reference of the Flyweight object
382 Flyweight& operator=(const Flyweight&) = default;
383 //! @brief The operator (=) overloading of Flyweight class.
384 //! @return reference of the Flyweight object
385 Flyweight& operator=(Flyweight&&) noexcept = default;
386
387 //! @brief The related operation.
388 virtual void operation() = 0;
389};
390
391//! @brief The unshared concrete flyweight.
392class UnsharedConcreteFlyweight : public Flyweight
393{
394public:
395 //! @brief Construct a new UnsharedConcreteFlyweight object.
396 //! @param intrinsicState - target intrinsic state
397 explicit UnsharedConcreteFlyweight(const int intrinsicState) : state{intrinsicState} {}
398
399 //! @brief The related operation.
400 void operation() override;
401
402private:
403 //! @brief Intrinsic state.
404 const int state{0};
405};
406
407//! @brief The concrete flyweight.
408class ConcreteFlyweight : public Flyweight
409{
410public:
411 //! @brief Construct a new ConcreteFlyweight object.
412 //! @param intrinsicState - target intrinsic state
413 explicit ConcreteFlyweight(const int intrinsicState) : state{intrinsicState} {}
414
415 //! @brief The related operation.
416 void operation() override;
417
418private:
419 //! @brief Intrinsic state.
420 const int state{0};
421};
422
423//! @brief Manage flyweights and ensure that flyweights are appropriately shared.
424class FlyweightFactory
425{
426public:
427 //! @brief Get the flyweight by key.
428 //! @param key - key of the flyweight
429 //! @return flyweight
430 std::unique_ptr<Flyweight>& getFlyweight(const int key);
431
432private:
433 //! @brief The flies.
434 std::map<int, std::unique_ptr<Flyweight>> flies;
435};
436
437extern std::ostringstream& output() noexcept;
438} // namespace flyweight
439
440//! @brief The proxy pattern.
441namespace proxy
442{
443//! @brief Make the proxy can be used anywhere a real subject is expected.
444class Subject
445{
446public:
447 //! @brief Construct a new Subject object.
448 Subject() = default;
449 //! @brief Destroy the Subject object.
450 virtual ~Subject() = default;
451 //! @brief Construct a new Subject object.
452 Subject(const Subject&) = default;
453 //! @brief Construct a new Subject object.
454 Subject(Subject&&) noexcept = default;
455 //! @brief The operator (=) overloading of Subject class.
456 //! @return reference of the Subject object
457 Subject& operator=(const Subject&) = default;
458 //! @brief The operator (=) overloading of Subject class.
459 //! @return reference of the Subject object
460 Subject& operator=(Subject&&) noexcept = default;
461
462 //! @brief The specific request.
463 virtual void request() = 0;
464};
465
466//! @brief The real object that the proxy represents.
467class RealSubject : public Subject
468{
469public:
470 //! @brief The specific request.
471 void request() override;
472};
473
474//! @brief Let the proxy access the real subject.
475class Proxy : public Subject
476{
477public:
478 //! @brief The specific request.
479 void request() override;
480
481private:
482 //! @brief Real subject.
483 std::unique_ptr<RealSubject> subject;
484
485protected:
486 //! @brief Get the real subject.
487 //! @return real subject
488 RealSubject& realSubject();
489};
490
491extern std::ostringstream& output() noexcept;
492} // namespace proxy
493} // namespace structural
494} // namespace design_pattern
495