Mediator_Pattern_2 - 8BitsCoding/RobotMentor GitHub Wiki
- Facilitates(촉진하다) communication between components.
- A component that facilitates communication betwwen other components without them necessarily begin aware of each other or having direct(reference) access to each other.
ChatRoom이라는 존재가 각 Object의 Mediator라고 보면 되겠다.
// main
#include "Person.hpp"
#include "ChatRoom.hpp"
int main()
{
ChatRoom room;
Person john{"John"};
Person jane{"Jane"};
room.join(&john);
room.join(&jane);
john.say("hi room");
jane.say("oh, hey john");
Person simon{"Simon"};
room.join(&simon);
simon.say("hi everyone!");
jane.pm("Simon", "glad you found us, simon!");
}
// Person.hpp
#include <string>
#include <vector>
using namepsace std;
struct ChatRoom;
struct Person {
string name;
ChatRoom* room{nullptr};
vector<string> chat_log;
Person(const string& name);
void say(const string& message) const;
void pm(const string& who, const string& message) const;
void recevice(const string& origin, const string& message);
bool operator==(const Person& rhs) const;
bool operator!=(const Person& rhs) const;
};
// Person.cpp
#include "Person.hpp"
#include "ChatRoom.hpp"
#include <iostream>
Person::Person(const string & name) : name(name) {}
void Person::say(const string& message) const
{
room->braodcast(name, message);
}
void Person::pm(const string& who, const string& message) const
{
room->message(name, who, message);
}
void recevice(const string& origin, const string& message)
{
string s{origin + ": \"" + message + "\""};
std::cout << "[" << name << "s chat session]" << s << "\n";
chat_log.emplace_back(s);
}
bool operator==(const Person& rhs) const
{
return name == rhs.name;
}
bool operator!=(const Person& rhs) const
{
return !(rhs == *this);
}
// ChatRoom.hpp
#include <vector>
struct ChatRoom {
vector<Person*> people;
void broadcast(const string& origin, const string& message);
void join(Person* p);
void message(const string& origin, const string& who, const string& message)
{
auto target = std::find_if(begin(people), end(people), [&](const Person* p){return p->name == who;}))
if(target != end(people))
{
(*target)->receive(origin, message);
}
}
};
// ChatRoom.cpp
#include "person.hpp"
#include <algorithm>
#include "ChatRoom.hpp"
void ChatRoom::broadcast(const string& origin, const string& message)
{
for(auto p : people)
if(p->name != origin)
p->receive(origin, message);
}
void ChatRoom::join(Person* p)
{
string join_msg = p->name + " joins the chat";
broadcast("room", join_msg);
p->room = this;
people.push_back(p);
}
// main.cpp
#include "headers.hpp"
#include "Person.hpp"
#include "ChatRoom.hpp"
int main()
{
ChatRoom room;
Person john{"John"};
Person jane{"Jane"};
room.join(&john);
room.join(&jane);
john.say("hi room");
jane.say("oh, hey john");
Person simon{"Simon"};
room.join(&simon);
simon.say("hi everyone!");
jane.pm("Simon", "glad you found us, simon!");
return 0;
}
// Person.hpp
#pragma once
#include <string>
#include <vector>
using namespace std;
struct ChatRoom;
struct Person {
string name;
ChatRoom* room{nullptr};
vector<string> chat_log;
Person(const string &name);
void say(const string& message) const;
void pm(const string& who,
const string& message) const;
void receive(const string& origin,
const string& message);
bool operator==(const Person &rhs) const;
bool operator!=(const Person &rhs) const;
};
// Person.cpp
#include "Person.hpp"
#include "ChatRoom.hpp"
#include <iostream>
Person::Person(const string &name) : name(name) {}
void Person::say(const string &message) const
{
room->broadcast(name, message);
}
void Person::pm(const string &who, const string &message) const
{
room->message(name, who, message);
}
void Person::receive(const string &origin, const string &message)
{
string s{origin + ": \"" + message + "\""};
std::cout << "[" << name << "'s chat session]" << s << "\n";
chat_log.emplace_back(s);
}
bool Person::operator==(const Person &rhs) const {
return name == rhs.name;
}
bool Person::operator!=(const Person &rhs) const {
return !(rhs == *this);
}
// ChatRoom.hpp
#pragma once
#include <algorithm>
struct ChatRoom
{
vector<Person*> people;
void broadcast(const string& origin,
const string& message);
void join(Person* p);
void message(const string& origin,
const string& who,
const string& message)
{
auto target = std::find_if(
begin(people),
end(people),
[&](const Person *p) {
return p->name == who;
});
if (target != end(people))
{
(*target)->receive(origin, message);
}
}
};
// ChatRoom.cpp
#include "person.hpp"
#include "ChatRoom.hpp"
void ChatRoom::broadcast(const string &origin, const string &message)
{
for (auto p : people)
if (p->name != origin)
p->receive(origin, message);
}
void ChatRoom::join(Person *p)
{
string join_msg = p->name + " joins the chat";
broadcast("room", join_msg);
p->room = this;
people.push_back(p);
}
Game이 Mediator라 생각하자
struct EventData
{
virtual void print() const = 0;
};
struct PlayerScoredData : EventData
{
string player_name;
int goals_scored_so_far;
PlayerScoredData(const string &player_name, int goals_scored_so_far) : player_name(player_name), goals_scored_so_far(goals_scored_so_far) {}
void print() const override
{
cout << player_name << " has scored! (their " << goals_scored_so_far << " goas)\n";
}
};
struct Game
{
signal<void(EventData*)> events;
};
struct Player
{
string name;
int goals_scored{0};
Game& game;
Player(const sting& name, Game& game) : name(name), game(game) {}
void score()
{
goals_scored++;
PlayerScoredData ps{name, goals_scored};
game.events(&ps);
}
};
struct Coach
{
Game& game;
Coach(Game& game) : game(game) {
game.events.connect([](EventData* e){
PlayerScoredData* ps = dynamic_cast<PlayerScoredData*>(e);
if(ps&&ps->goals_scored_so_far < 3)
{
cout << "coach_says : well done," << ps->player_name << "!\n";
}
});
}
};
int main()
{
Game game;
Player player{"sam", game};
Coach coach{game};
player.score();
player.score();
player.score();
return 0;
}
#include <iostream>
#include <string>
#include <vector>
struct Game;
using namespace std;
#include <boost/signals2.hpp>
using namespace boost::signals2;
struct EventData
{
virtual ~EventData() = default;
virtual void print() const = 0;
};
struct Player;
struct PlayerScoredData : EventData
{
string player_name;
int goals_scored_so_far;
PlayerScoredData(const string& player_name, const int goals_scored_so_far)
: player_name(player_name),
goals_scored_so_far(goals_scored_so_far)
{
}
void print() const override
{
cout << player_name << " has scored! (their "
<< goals_scored_so_far << " goal)" << "\n";
}
};
struct Game
{
signal<void(EventData*)> events; // observer
};
struct Player
{
string name;
int goals_scored = 0;
Game& game;
Player(const string& name, Game& game)
: name(name),
game(game)
{
}
void score()
{
goals_scored++;
PlayerScoredData ps{name, goals_scored};
game.events(&ps);
}
};
struct Coach
{
Game& game;
explicit Coach(Game& game)
: game(game)
{
// celebrate if player has scored <3 goals
game.events.connect([](EventData* e)
{
PlayerScoredData* ps = dynamic_cast<PlayerScoredData*>(e);
if (ps && ps->goals_scored_so_far < 3)
{
cout << "coach says: well done, " << ps->player_name << "\n";
}
});
}
};
int main()
{
Game game;
Player player{ "Sam", game };
Coach coach{ game };
player.score();
player.score();
player.score(); // ignored by coach
getchar();
return 0;
}