Skip to content

Commit 8816ce4

Browse files
authored
Merge pull request #18 from urboob21/dev_branch
id 1763705535
2 parents 784e4ef + 3dc783c commit 8816ce4

4 files changed

Lines changed: 185 additions & 1 deletion

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ set(APP_SOURCES
101101
"src/patterns/behavioral/ChainOfCommand.cpp"
102102
"src/patterns/behavioral/Command.cpp"
103103
"src/patterns/behavioral/Iterator.cpp"
104+
"src/patterns/behavioral/Mediator.cpp"
104105
)
105106

106107
# Test files

‎docs/uml/patterns_behavioral_iterator.drawio.svg‎

Lines changed: 1 addition & 1 deletion
Loading

‎docs/uml/patterns_behavioral_mediator.drawio.svg‎

Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Mediator is a behavioral design pattern that lets you reduce chaotic dependencies between objects.
2+
// The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
3+
// Usage examples: The most popular usage of the Mediator pattern in C++ code is facilitating communications between GUI components of an app.
4+
// The synonym of the Mediator is the `Controller` part of MVC pattern.
5+
// Appicability:
6+
// (*) when your collection has a complex data structure under the hood, but you want to hide its complexity from clients (either for convenience or security reasons).
7+
// (**) when you can’t reuse a component in a different program because it’s too dependent on other components.
8+
// (***) when you find yourself creating tons of component subclasses just to reuse some basic behavior in various contexts.
9+
10+
// UML: docs/uml/patterns_behavioral_mediator.drawio.svg
11+
12+
#include <iostream>
13+
#include <string>
14+
#include <vector>
15+
namespace
16+
{
17+
namespace Mediator
18+
{
19+
20+
enum class Event
21+
{
22+
CREATE = 0,
23+
READ,
24+
UPDATE,
25+
DELETE,
26+
};
27+
28+
static inline const char *getEventName(const Event &e)
29+
{
30+
switch (e)
31+
{
32+
case Event::CREATE:
33+
return "CREATE";
34+
case Event::READ:
35+
return "READ";
36+
case Event::UPDATE:
37+
return "UPDATE";
38+
case Event::DELETE:
39+
return "DELETE";
40+
}
41+
return "invalid_event";
42+
}
43+
44+
class IComponent
45+
{
46+
public:
47+
virtual ~IComponent() = default;
48+
49+
virtual void send(const Event e) = 0;
50+
virtual void receive(const Event e) = 0;
51+
};
52+
53+
/**
54+
* The Mediator interface declares methods of communication with components, which usually include just a single notification method.
55+
* Components may pass any context as arguments of this method, including their own objects,
56+
* but only in such a way that no coupling occurs between a receiving component and the sender’s class.
57+
*/
58+
class IMediator
59+
{
60+
public:
61+
virtual ~IMediator() = default;
62+
virtual void registerComponent(IComponent *const c) = 0;
63+
virtual void notify(IComponent *sender, const Event &e) = 0;
64+
};
65+
66+
/**
67+
* Concrete Mediators implement cooperative behavior by coordinating several components.
68+
* Concrete mediators often keep references to all components they manage and sometimes even manage their lifecycle.
69+
*/
70+
class ComponentMediator : public IMediator
71+
{
72+
private:
73+
std::vector<IComponent *> m_components;
74+
75+
public:
76+
void registerComponent(IComponent *const c) override
77+
{
78+
m_components.push_back(c);
79+
}
80+
81+
void notify(IComponent *const sender, const Event &e) override
82+
{
83+
for (auto c : m_components)
84+
{
85+
if (c != sender)
86+
{
87+
c->receive(e);
88+
}
89+
}
90+
}
91+
};
92+
93+
/**
94+
* Components are various classes that contain some business logic.
95+
* Each component has a reference to a mediator, declared with the type of the mediator interface.
96+
* The component isn’t aware of the actual class of the mediator, so you can reuse the component in other programs by linking it to a different mediator.
97+
*/
98+
class AbstractComponent : public IComponent
99+
{
100+
private:
101+
const std::string m_id;
102+
103+
protected:
104+
IMediator *m_mediator;
105+
void log(const Event &e, const std::string &msg) const
106+
{
107+
std::cout << "\t" + msg + "-id:" + m_id + "-event:" + getEventName(e) + "\n";
108+
}
109+
110+
public:
111+
explicit AbstractComponent(const std::string &id, IMediator *const m = nullptr) : m_id{id}, m_mediator{m} {};
112+
};
113+
114+
/**
115+
* Concrete Components implement various functionality. They don't depend on
116+
* other components. They also don't depend on any concrete mediator classes.
117+
*/
118+
class ConreteComponent : public AbstractComponent
119+
{
120+
public:
121+
explicit ConreteComponent(const std::string &id, IMediator *const m = nullptr) : AbstractComponent{id, m} {}
122+
123+
void send(const Event e) override
124+
{
125+
log(e, "[SEND]");
126+
if (m_mediator != nullptr)
127+
m_mediator->notify(this, e);
128+
}
129+
130+
void receive(const Event e) override
131+
{
132+
log(e, "[RECV]");
133+
// Additional handling logic can go here
134+
}
135+
};
136+
137+
namespace Client
138+
{
139+
void clientCode(IComponent *comp)
140+
{
141+
comp->send(Event::READ);
142+
}
143+
}
144+
145+
void run()
146+
{
147+
IMediator *mediator = new ComponentMediator();
148+
IComponent *c1 = new ConreteComponent("1763700876", mediator);
149+
IComponent *c2 = new ConreteComponent("1763700882", mediator);
150+
IComponent *c3 = new ConreteComponent("1763700899", mediator);
151+
IComponent *c4 = new ConreteComponent("1763700900", mediator);
152+
153+
// Only c1, c3, c4 receive notifications.
154+
mediator->registerComponent(c1);
155+
mediator->registerComponent(c3);
156+
mediator->registerComponent(c4);
157+
158+
// c2 triggers event => observed by others
159+
Client::clientCode(c2);
160+
161+
delete mediator;
162+
delete c1;
163+
delete c2;
164+
delete c3;
165+
delete c4;
166+
}
167+
}
168+
}
169+
170+
struct MediatorAutoRunner
171+
{
172+
MediatorAutoRunner()
173+
{
174+
std::cout << "\n--- Mediator Pattern Example ---\n";
175+
Mediator::run();
176+
}
177+
};
178+
179+
static MediatorAutoRunner instance;

0 commit comments

Comments
 (0)