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.

Chat Room Example

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);
}

Chat Room Example 전체코드

// 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);
}

Event-Broker

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;
}

Event-Broker 전체코드

#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;
}
⚠️ **GitHub.com Fallback** ⚠️