중재자(Mediator) 패턴
채팅 시스템 예제를 통한 중재자 패턴 이해
중재자(Mediator) 패턴
중재자 패턴(Mediator Pattern)은 객체 간의 복잡한 상호작용을 중재자 객체가 담당하도록 하여, 개별 객체들이 서로 직접 통신하지 않고 중재자를 통해 간접적으로 소통하도록 하는 구조적인 디자인 패턴이다.
이 패턴을 사용하면 객체 간의 결합도를 줄일 수 있어 유지보수가 쉬워지고 코드가 더 모듈화된다. 특히 GUI 이벤트 처리나 채팅 시스템 같은 곳에서 유용하게 쓰인다.
장점
- 객체 간 결합도 감소: User 객체들이 서로 직접 참조하지 않고 중재자 객체를 통해서만 통신 → 결합도가 낮아짐
- 유지보수성 향상: 중재자를 수정하면 모든 관련 객체의 동작이 조정 → 확장성, 유지보수성 향상
- 중앙 집중 제어: 복잡한 다자간 관계를 단순화하여 코드의 가독성이 향상
주의점
- 중재자의 복잡성이 증가
- 기능이 많아지면 중재자가 거대한 객체(God Object)가 될 위험성 있음
- 로직이 어려워지고 유지보수가 어려워짐
- 특정 객체에 대한 의존성이 완전히 사라지지 않음
- 객체 간의 직접적인 의존성이 줄어들지만, 객체들이 중재자에게 의존
- 중재자가 바뀌면 모든 관련된 객체들의 동작이 변경될 가능성이 있음
- 객체 간의 직접적인 메시징보다 성능이 저하
- 실시간 처리가 필요한 시스템에서는 불필요한 중간 처리로 인해 속도가 저하될 가능성이 있음
예시
C++을 이용하여 예시 코드를 작성하였다. 아래 링크에서 전체를 확인할 수 있다.
https://github.com/grade-e/mediator-cpp-container
Class diagram
classDiagram
class ChatMediator {
<<interface>>
+void sendMessage(string message, User* sender)
+void addUser(shared_ptr<User> user)
}
class User {
-string name
-shared_ptr<ChatMediator> mediator
+User(string name, shared_ptr<ChatMediator> mediator)
+void send(string message)
+void receive(string message)
+string getName()
}
class ChatRoom {
+vector<shared_ptr<User>> users
+void addUser(shared_ptr<User> user)
+void sendMessage(string message, User* sender)
}
ChatMediator <|.. ChatRoom
ChatRoom --> User : manages
User --> ChatMediator : interacts
코드
Class: ChatMediator
- 메서드를 정의하여
User사이의 메시지 중재 역할
1
2
3
4
5
6
7
class ChatMediator {
public:
virtual void sendMessage(const std::string& message,
class User* sender) = 0;
virtual void addUser(std::shared_ptr<User> user) = 0;
virtual ~ChatMediator() = default;
};
Class: ChatRoom
User객체들을 리스트로 관리sendMessage()를 통해 특정 사용자를 제외한 모든 사용자에게 메시지를 전달
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ChatRoom : public ChatMediator {
private:
std::vector<std::shared_ptr<User>> users;
public:
void addUser(std::shared_ptr<User> user) override { users.push_back(user); }
void sendMessage(const std::string& message, User* sender) override {
for (auto& user : users) {
if (user.get() != sender) { // 자기 자신에게는 메시지를 보내지 않음
user->receive(sender->getName() + ": " + message);
}
}
}
};
Class: User
send()는 메시지를 중재자에게 전달receive()는 다른 사용자로부터 메시지를 받을 때 호출name과ChatMediator의 참조를 가짐send()로 메시지를 보내고,receive()로 메시지를 받음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class User {
protected:
std::string name;
std::shared_ptr<ChatMediator> mediator;
public:
User(const std::string& name, std::shared_ptr<ChatMediator> mediator)
: name(name), mediator(mediator) {}
virtual void send(const std::string& message) {
std::cout << name << " sends: " << message << std::endl;
mediator->sendMessage(message, this);
}
virtual void receive(const std::string& message) {
std::cout << name << " receives: " << message << std::endl;
}
std::string getName() const { return name; }
};
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
// 중재자 객체 생성
auto chatRoom = std::make_shared<ChatRoom>();
// 사용자 추가
auto user1 = std::make_shared<User>("Alice", chatRoom);
auto user2 = std::make_shared<User>("Bob", chatRoom);
auto user3 = std::make_shared<User>("Charlie", chatRoom);
chatRoom->addUser(user1);
chatRoom->addUser(user2);
chatRoom->addUser(user3);
// 메시지 전송
user1->send("Hello, everyone!");
user2->send("Hey Alice!");
user3->send("Good morning!");
return 0;
}
실행 결과
1
2
3
4
5
6
7
8
9
Alice sends: Hello, everyone!
Bob receives: Alice: Hello, everyone!
Charlie receives: Alice: Hello, everyone!
Bob sends: Hey Alice!
Alice receives: Bob: Hey Alice!
Charlie receives: Bob: Hey Alice!
Charlie sends: Good morning!
Alice receives: Charlie: Good morning!
Bob receives: Charlie: Good morning!
This post is licensed under CC BY 4.0 by the author.