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