1//! @file behavioral.hpp
2//! @author ryftchen
3//! @brief The declarations (behavioral) 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 Behavioral-related functions in the design pattern module.
18namespace behavioral
19{
20//! @brief Brief function description.
21//! @return function description (module_function)
22inline static const char* description() noexcept
23{
24 return "DP_BEHAVIORAL";
25}
26extern const char* version() noexcept;
27
28//! @brief The chain of responsibility pattern.
29namespace chain_of_responsibility
30{
31//! @brief Handle requests that they are responsible for. Optionally implement the successor link.
32class Handler
33{
34public:
35 //! @brief Destroy the Handler object.
36 virtual ~Handler() = default;
37
38 //! @brief Set the handler.
39 //! @param handler - target handler
40 virtual void setHandler(std::shared_ptr<Handler> handler);
41 //! @brief Handle the request.
42 virtual void handleRequest();
43
44private:
45 //! @brief The successor.
46 std::shared_ptr<Handler> successor;
47};
48
49//! @brief The concrete handler.
50class ConcreteHandler1 : public Handler
51{
52public:
53 //! @brief Handle the request.
54 void handleRequest() override;
55
56private:
57 //! @brief Check whether it can handle the request.
58 //! @return can handle or not
59 [[nodiscard]] bool canHandle() const;
60};
61
62//! @brief The concrete handler.
63class ConcreteHandler2 : public Handler
64{
65public:
66 //! @brief Handle the request.
67 void handleRequest() override;
68
69private:
70 //! @brief Check whether it can handle the request.
71 //! @return can handle or not
72 [[nodiscard]] bool canHandle() const;
73};
74
75extern std::ostringstream& output() noexcept;
76} // namespace chain_of_responsibility
77
78//! @brief The command pattern.
79namespace command
80{
81//! @brief Receiver associated with the command.
82class Receiver
83{
84public:
85 //! @brief Perform the operations associated with carrying out the request.
86 void action() const;
87};
88
89//! @brief Implement the execution in command.
90class Command
91{
92public:
93 //! @brief Destroy the Command object.
94 virtual ~Command() = default;
95
96 //! @brief Execute the command.
97 virtual void execute() = 0;
98
99protected:
100 //! @brief Construct a new Command object.
101 Command() = default;
102};
103
104//! @brief The concrete command.
105class ConcreteCommand : public Command
106{
107public:
108 //! @brief Construct a new ConcreteCommand object.
109 //! @param receiver - receiver associated with the command
110 explicit ConcreteCommand(std::shared_ptr<Receiver> receiver) : receiver{std::move(receiver)} {}
111
112 //! @brief Execute the command.
113 void execute() override;
114
115private:
116 //! @brief The receiver.
117 const std::shared_ptr<Receiver> receiver;
118};
119
120//! @brief Invoke the corresponding operation.
121class Invoker
122{
123public:
124 //! @brief Set the command.
125 //! @param c - command
126 void set(std::shared_ptr<Command> c);
127 //! @brief Ask the command to carry out the request.
128 void confirm();
129
130private:
131 //! @brief The command.
132 std::shared_ptr<Command> command;
133};
134
135extern std::ostringstream& output() noexcept;
136} // namespace command
137
138//! @brief The interpreter pattern.
139namespace interpreter
140{
141//! @brief Global context.
142class Context
143{
144public:
145 //! @brief Set the pair of the expression and the value.
146 //! @param expr - expression
147 //! @param val - value
148 void set(const std::string& expr, const bool val);
149 //! @brief Get the value by expression.
150 //! @param expr - expression
151 //! @return value
152 bool get(const std::string& expr);
153
154private:
155 //! @brief The variables.
156 std::map<std::string, bool> vars;
157};
158
159//! @brief The abstract interpret operation.
160class AbstractExpression
161{
162public:
163 //! @brief Destroy the AbstractExpression object.
164 virtual ~AbstractExpression() = default;
165
166 //! @brief The interpret that is common to all nodes in the abstract syntax tree.
167 //! @param context - global context
168 //! @return resulting value
169 virtual bool interpret(const std::shared_ptr<Context>& context);
170};
171
172//! @brief The terminal interpret operation. An instance is required for every terminal symbol in a sentence.
173class TerminalExpression : public AbstractExpression
174{
175public:
176 //! @brief Construct a new TerminalExpression object.
177 //! @param value - target value
178 explicit TerminalExpression(const std::string_view value) : value{value} {}
179
180 //! @brief The interpret that associated with terminal symbols in the grammar.
181 //! @param context - global context
182 //! @return resulting value
183 bool interpret(const std::shared_ptr<Context>& context) override;
184
185private:
186 //! @brief The value of the terminal expression.
187 const std::string value;
188};
189
190//! @brief The non-terminal interpret operation. One such class is required for every rule in grammar.
191class NonTerminalExpression : public AbstractExpression
192{
193public:
194 //! @brief Construct a new NonTerminalExpression object.
195 //! @param left - target left operation
196 //! @param right - target right operation
197 NonTerminalExpression(std::shared_ptr<AbstractExpression> left, std::shared_ptr<AbstractExpression> right) :
198 leftOp{std::move(left)}, rightOp{std::move(right)}
199 {
200 }
201
202 //! @brief The interpret that associated with non-terminal symbols in the grammar.
203 //! @param context - global context
204 //! @return resulting value
205 bool interpret(const std::shared_ptr<Context>& context) override;
206
207private:
208 //! @brief The left operation of the non-terminal expression.
209 std::shared_ptr<AbstractExpression> leftOp;
210 //! @brief The right operation of the non-terminal expression.
211 std::shared_ptr<AbstractExpression> rightOp;
212};
213
214extern std::ostringstream& output() noexcept;
215} // namespace interpreter
216
217//! @brief The iterator pattern.
218namespace iterator
219{
220//! @brief Manage the current index of the iterator. A set of methods for traversing over items.
221class Iterator
222{
223public:
224 //! @brief Destroy the Iterator object.
225 virtual ~Iterator() = default;
226
227 //! @brief Set the current index to the first.
228 virtual void first() = 0;
229 //! @brief Set the current index to the next.
230 virtual void next() = 0;
231 //! @brief Check whether the traversal is done.
232 //! @return be done or not
233 [[nodiscard]] virtual bool isDone() const = 0;
234 //! @brief Get the item by current index.
235 //! @return current item
236 [[nodiscard]] virtual int currentItem() const = 0;
237};
238
239//! @brief The aggregate decouples the client from the implementation of the collection of items.
240class Aggregate
241{
242public:
243 //! @brief Destroy the Aggregate object.
244 virtual ~Aggregate() = default;
245
246 //! @brief Create an iterator.
247 //! @return iterator
248 virtual std::shared_ptr<Iterator> createIterator() = 0;
249};
250
251//! @brief The concrete aggregate.
252class ConcreteAggregate : public Aggregate, public std::enable_shared_from_this<ConcreteAggregate>
253{
254public:
255 //! @brief Construct a new ConcreteAggregate object.
256 //! @param size - size of items
257 explicit ConcreteAggregate(const std::uint32_t size);
258
259 //! @brief Create an iterator.
260 //! @return iterator
261 std::shared_ptr<Iterator> createIterator() override;
262 //! @brief Get the size of items.
263 //! @return size of items
264 std::uint32_t size() const;
265 //! @brief Get the item by index.
266 //! @param index - index of item
267 //! @return item
268 int at(const std::uint32_t index);
269
270private:
271 //! @brief Collection of items.
272 std::unique_ptr<int[]> list;
273 //! @brief Size of items.
274 const std::uint32_t count{0};
275};
276
277//! @brief The concrete iterator.
278class ConcreteIterator : public Iterator
279{
280public:
281 //! @brief Construct a new ConcreteIterator object.
282 //! @param aggregate - target aggregate
283 explicit ConcreteIterator(std::shared_ptr<ConcreteAggregate> aggregate) : aggregate{std::move(aggregate)} {}
284
285 //! @brief Set the current index to the first.
286 void first() override;
287 //! @brief Set the current index to the next.
288 void next() override;
289 //! @brief Check whether the traversal is done.
290 //! @return be done or not
291 [[nodiscard]] bool isDone() const override;
292 //! @brief Get the item by current index.
293 //! @return current item
294 [[nodiscard]] int currentItem() const override;
295
296private:
297 //! @brief Aggregate to be iterated.
298 const std::shared_ptr<ConcreteAggregate> aggregate;
299 //! @brief Current index.
300 std::uint32_t index{0};
301};
302
303extern std::ostringstream& output() noexcept;
304} // namespace iterator
305
306//! @brief The mediator pattern.
307namespace mediator
308{
309class Colleague;
310
311//! @brief Implement cooperative behavior by coordinating colleagues.
312class Mediator
313{
314public:
315 //! @brief Destroy the Mediator object.
316 virtual ~Mediator() = default;
317
318 //! @brief Add colleague.
319 //! @param colleague - target colleague
320 virtual void add(const std::shared_ptr<Colleague>& colleague) = 0;
321 //! @brief Distribute message.
322 //! @param sender - sender in colleagues
323 //! @param msg - message from sender
324 virtual void distribute(const std::shared_ptr<Colleague>& sender, const std::string_view msg) = 0;
325
326protected:
327 //! @brief Construct a new Mediator object.
328 Mediator() = default;
329};
330
331//! @brief The concrete mediator.
332class ConcreteMediator : public Mediator
333{
334public:
335 //! @brief Add colleague.
336 //! @param colleague - target colleague
337 void add(const std::shared_ptr<Colleague>& colleague) override;
338 //! @brief Distribute message.
339 //! @param sender - sender in colleagues
340 //! @param msg - message from sender
341 void distribute(const std::shared_ptr<Colleague>& sender, const std::string_view msg) override;
342
343private:
344 //! @brief Collection of colleagues.
345 std::vector<std::weak_ptr<Colleague>> colleagues;
346};
347
348//! @brief The colleague communicates with its mediator.
349//! Whenever it would have otherwise communicated with another colleague.
350class Colleague
351{
352public:
353 //! @brief Construct a new Colleague object.
354 //! @param mediator - target mediator
355 //! @param id - target id
356 Colleague(const std::shared_ptr<Mediator>& mediator, const std::uint32_t id) : mediator{mediator}, id{id} {}
357 //! @brief Destroy the Colleague object.
358 virtual ~Colleague() = default;
359
360 //! @brief Get the id of the colleague.
361 //! @return id of the colleague
362 [[nodiscard]] std::uint32_t getId() const;
363 //! @brief Send message.
364 //! @param msg - sending message
365 virtual void send(const std::string_view msg) = 0;
366 //! @brief Receive message.
367 //! @param msg - receiving message
368 virtual void receive(const std::string_view msg) = 0;
369
370protected:
371 //! @brief Mediator of the colleague.
372 const std::weak_ptr<Mediator> mediator;
373 //! @brief Id of the colleague.
374 const std::uint32_t id{0};
375};
376
377//! @brief The concrete colleague.
378class ConcreteColleague : public Colleague, public std::enable_shared_from_this<ConcreteColleague>
379{
380public:
381 //! @brief Construct a new ConcreteColleague object.
382 //! @param mediator - target mediator
383 //! @param id - target id
384 ConcreteColleague(const std::shared_ptr<Mediator>& mediator, const std::uint32_t id) : Colleague(mediator, id) {}
385
386 //! @brief Send message.
387 //! @param msg - sending message
388 void send(const std::string_view msg) override;
389 //! @brief Receive message.
390 //! @param msg - receiving message
391 void receive(const std::string_view msg) override;
392};
393
394extern std::ostringstream& output() noexcept;
395} // namespace mediator
396
397//! @brief The memento pattern.
398namespace memento
399{
400//! @brief Store the internal state of the originator. Protect against access by other than the originator.
401class Memento
402{
403private:
404 friend class Originator;
405 //! @brief Construct a new Memento object.
406 //! @param state - target state
407 explicit Memento(const int state) : state{state} {}
408
409 //! @brief State of memento.
410 int state{0};
411 //! @brief Set the state of memento.
412 //! @param s - target state
413 void setState(const int s);
414 //! @brief Get the state of memento.
415 //! @return state of memento
416 [[nodiscard]] int getState() const;
417};
418
419//! @brief Create the memento containing a snapshot of its current internal state.
420//! Use the memento to restore its internal state.
421class Originator
422{
423public:
424 //! @brief Set the state of originator.
425 //! @param s - target state
426 void setState(const int s);
427 //! @brief Get the state of originator.
428 //! @return state of originator
429 [[nodiscard]] int getState() const;
430 //! @brief Set the state of originator by memento.
431 //! @param memento - target memento
432 void setMemento(const std::shared_ptr<Memento>& memento);
433 //! @brief Create the memento.
434 //! @return memento
435 [[nodiscard]] std::shared_ptr<Memento> createMemento() const;
436
437private:
438 //! @brief State of originator.
439 int state{0};
440};
441
442//! @brief Safeguard memento.
443class CareTaker
444{
445public:
446 //! @brief Construct a new CareTaker object.
447 //! @param originator - target originator
448 explicit CareTaker(const std::shared_ptr<Originator>& originator) : originator{originator} {}
449
450 //! @brief Save the current state to history.
451 void save();
452 //! @brief Undo the last state.
453 void undo();
454
455private:
456 //! @brief Specific originator.
457 const std::shared_ptr<Originator> originator;
458 //! @brief State history.
459 std::vector<std::shared_ptr<Memento>> history;
460};
461
462extern std::ostringstream& output() noexcept;
463} // namespace memento
464
465//! @brief The observer pattern.
466namespace observer
467{
468class Subject;
469
470//! @brief Store state of interest to the observer. Send a notification to its observers when its state changes.
471class Observer
472{
473public:
474 //! @brief Destroy the Observer object.
475 virtual ~Observer() = default;
476
477 //! @brief Get the state of observer.
478 //! @return state of observer
479 [[nodiscard]] virtual int getState() const = 0;
480 //! @brief Update the state of observer by subject.
481 //! @param subject - target subject
482 virtual void update(const std::weak_ptr<Subject>& subject) = 0;
483};
484
485//! @brief Attach, detach and notify observers.
486class Subject : public std::enable_shared_from_this<Subject>
487{
488public:
489 //! @brief Destroy the Subject object.
490 virtual ~Subject() = default;
491
492 //! @brief Attach observer.
493 //! @param observer - observer to be attached
494 void attach(const std::shared_ptr<Observer>& observer);
495 //! @brief Detach observer by index.
496 //! @param index - observer index
497 void detach(const int index);
498 //! @brief Notify all observers.
499 void notify();
500 //! @brief Get the state of subject.
501 //! @return state of subject
502 virtual int getState() const = 0;
503 //! @brief Set the state of subject.
504 //! @param s - target state of subject
505 virtual void setState(const int s) = 0;
506
507private:
508 //! @brief Collection of observers.
509 std::vector<std::weak_ptr<Observer>> observers;
510};
511
512//! @brief The concrete observer.
513class ConcreteObserver : public Observer
514{
515public:
516 //! @brief Construct a new ConcreteObserver object.
517 //! @param state - target state of observer
518 explicit ConcreteObserver(const int state) : observerState{state} {}
519
520 //! @brief Get the state of observer.
521 //! @return state of observer
522 [[nodiscard]] int getState() const override;
523 //! @brief Update the state of observer by subject.
524 //! @param subject - target subject
525 void update(const std::weak_ptr<Subject>& subject) override;
526
527private:
528 //! @brief State of observer.
529 int observerState{0};
530};
531
532//! @brief The concrete subject.
533class ConcreteSubject : public Subject
534{
535public:
536 //! @brief Get the state of subject.
537 //! @return state of subject
538 int getState() const override;
539 //! @brief Set the state of subject.
540 //! @param s - target state of subject
541 void setState(const int s) override;
542
543private:
544 //! @brief State of subject.
545 int subjectState{0};
546};
547
548extern std::ostringstream& output() noexcept;
549} // namespace observer
550
551//! @brief The state pattern.
552namespace state
553{
554//! @brief Behaviors associated with a particular state of the context.
555class State
556{
557public:
558 //! @brief Destroy the State object.
559 virtual ~State() = default;
560
561 //! @brief Handle in the state.
562 virtual void handle() = 0;
563};
564
565//! @brief The concrete state.
566class ConcreteStateA : public State
567{
568public:
569 //! @brief Handle in the state.
570 void handle() override;
571};
572
573//! @brief The concrete state.
574class ConcreteStateB : public State
575{
576public:
577 //! @brief Handle in the state.
578 void handle() override;
579};
580
581//! @brief Interest in clients.
582class Context
583{
584public:
585 //! @brief Set the state of context.
586 //! @param s - target state
587 void setState(std::unique_ptr<State> s);
588 //! @brief Request handling.
589 void request();
590
591private:
592 //! @brief State of context.
593 std::unique_ptr<State> state;
594};
595
596extern std::ostringstream& output() noexcept;
597} // namespace state
598
599//! @brief The strategy pattern.
600namespace strategy
601{
602//! @brief Implement the algorithm using the strategy interface. Common to all supported algorithms.
603class Strategy
604{
605public:
606 //! @brief Destroy the Strategy object.
607 virtual ~Strategy() = default;
608
609 //! @brief The interface of the algorithm.
610 virtual void algorithmInterface() = 0;
611};
612
613//! @brief The concrete strategy.
614class ConcreteStrategyA : public Strategy
615{
616public:
617 //! @brief The interface of the algorithm.
618 void algorithmInterface() override;
619};
620
621//! @brief The concrete strategy.
622class ConcreteStrategyB : public Strategy
623{
624public:
625 //! @brief The interface of the algorithm.
626 void algorithmInterface() override;
627};
628
629//! @brief Maintain reference to the strategy object.
630class Context
631{
632public:
633 //! @brief Construct a new Context object.
634 //! @param strategy - target strategy
635 explicit Context(std::unique_ptr<Strategy> strategy) : strategy{std::move(strategy)} {}
636
637 //! @brief The interface of the context.
638 void contextInterface();
639
640private:
641 //! @brief Strategy of context.
642 std::unique_ptr<Strategy> strategy;
643};
644
645extern std::ostringstream& output() noexcept;
646} // namespace strategy
647
648//! @brief The template method pattern.
649namespace template_method
650{
651//! @brief Implement the template method defining the skeleton of the algorithm.
652class AbstractClass
653{
654public:
655 //! @brief Destroy the AbstractClass object.
656 virtual ~AbstractClass() = default;
657
658 //! @brief The template method.
659 void templateMethod();
660 //! @brief The primitive operation 1.
661 virtual void primitiveOperation1() = 0;
662 //! @brief The primitive operation 2.
663 virtual void primitiveOperation2() = 0;
664};
665
666//! @brief Implement the primitive operations to carry out specific steps of the algorithm.
667class ConcreteClass : public AbstractClass
668{
669public:
670 //! @brief The primitive operation 1.
671 void primitiveOperation1() override;
672 //! @brief The primitive operation 2.
673 void primitiveOperation2() override;
674};
675
676extern std::ostringstream& output() noexcept;
677} // namespace template_method
678
679//! @brief The visitor pattern.
680namespace visitor
681{
682class ConcreteElementA;
683class ConcreteElementB;
684
685//! @brief Implement the algorithm's fragment defined for the structure's corresponding element.
686class Visitor
687{
688public:
689 //! @brief Destroy the Visitor object.
690 virtual ~Visitor() = default;
691
692 //! @brief Visit element A.
693 //! @param element - element to be visited
694 virtual void visitElementA(const std::shared_ptr<ConcreteElementA>& element) = 0;
695 //! @brief Visit element B.
696 //! @param element - element to be visited
697 virtual void visitElementB(const std::shared_ptr<ConcreteElementB>& element) = 0;
698};
699
700//! @brief The concrete visitor.
701class ConcreteVisitor1 : public Visitor
702{
703public:
704 //! @brief Visit element A.
705 //! @param element - element to be visited
706 void visitElementA(const std::shared_ptr<ConcreteElementA>& element) override;
707 //! @brief Visit element B.
708 //! @param element - element to be visited
709 void visitElementB(const std::shared_ptr<ConcreteElementB>& element) override;
710};
711
712//! @brief The concrete visitor.
713class ConcreteVisitor2 : public Visitor
714{
715public:
716 //! @brief Visit element A.
717 //! @param element - element to be visited
718 void visitElementA(const std::shared_ptr<ConcreteElementA>& element) override;
719 //! @brief Visit element B.
720 //! @param element - element to be visited
721 void visitElementB(const std::shared_ptr<ConcreteElementB>& element) override;
722};
723
724//! @brief Implement the accept operation that takes a visitor as an argument.
725class Element
726{
727public:
728 //! @brief Destroy the Element object.
729 virtual ~Element() = default;
730
731 //! @brief Accept visitor.
732 //! @param visitor - visitor to be accepted
733 virtual void accept(Visitor& visitor) = 0;
734};
735
736//! @brief The concrete element.
737class ConcreteElementA : public Element, public std::enable_shared_from_this<ConcreteElementA>
738{
739public:
740 //! @brief Accept visitor.
741 //! @param visitor - visitor to be accepted
742 void accept(Visitor& visitor) override;
743};
744
745//! @brief The concrete element.
746class ConcreteElementB : public Element, public std::enable_shared_from_this<ConcreteElementB>
747{
748public:
749 //! @brief Accept visitor.
750 //! @param visitor - visitor to be accepted
751 void accept(Visitor& visitor) override;
752};
753
754extern std::ostringstream& output() noexcept;
755} // namespace visitor
756} // namespace behavioral
757} // namespace design_pattern
758