중재자(Mediator) 패턴은 객체들 사이의 상호작용을 캡슐화하여 객체간의 직접적인 통신을 방지하고, 중재자 객체를 통해 간접적으로 상호작용할 수 있게 하는 디자인 패턴이다.
using UnityEngine;
using System.Collections.Generic;
// Mediator 인터페이스
public interface IChatMediator
{
void SendMessage(string message, ChatMember sender);
void AddMember(ChatMember member);
}
// Concrete Mediator
public class ChatRoom : IChatMediator
{
private List<ChatMember> members = new List<ChatMember>();
public void AddMember(ChatMember member)
{
members.Add(member);
}
public void SendMessage(string message, ChatMember sender)
{
foreach (var member in members)
{
// 메시지를 보낸 멤버를 제외한 모든 멤버에게 메시지 전달
if (member != sender)
{
member.ReceiveMessage(message, sender.Name);
}
}
}
}
public class WhisperChatRoom : IChatMediator
{
private ChatMember member;
public void AddMember(ChatMember member)
{
this.member = member;
}
public void SendMessage(string message, ChatMember sender)
{
member.ReceiveMessage(message, sender.Name);
}
}
public class PrivateChatRoom : IChatMediator
{
private List<ChatMember> members = new List<ChatMember>();
public void AddMember(ChatMember member)
{
if (member.isPrivate)
members.Add(member);
}
public void SendMessage(string message, ChatMember sender)
{
foreach (var member in members)
{
// 메시지를 보낸 멤버를 제외한 모든 멤버에게 메시지 전달
if (member != sender)
{
member.ReceiveMessage(message, sender.Name);
}
}
}
}
// Colleague 클래스
public abstract class ChatMember : MonoBehaviour
{
public bool isPrivate;
protected IChatMediator mediator;
public string Name { get; private set; }
public void SetMediator(IChatMediator mediator)
{
this.mediator = mediator;
}
public void SetName(string name)
{
this.Name = name;
}
public abstract void Send(string message);
public abstract void ReceiveMessage(string message, string senderName);
}
// Concrete Colleague
public class Player_3 : ChatMember
{
public override void Send(string message)
{
Debug.Log($"{Name} sending: {message}");
mediator.SendMessage(message, this);
}
public override void ReceiveMessage(string message, string senderName)
{
Debug.Log($"{Name} received: {message} from {senderName}");
}
}
// Concrete Colleague
public class AI : ChatMember
{
public override void Send(string message)
{
Debug.Log($"AI {Name} sending: {message}");
mediator.SendMessage(message, this);
}
public override void ReceiveMessage(string message, string senderName)
{
Debug.Log($"AI {Name} received: {message} from {senderName}");
// AI could process the message here and potentially respond
}
}
// 사용 예시
public class GameManager_3 : MonoBehaviour
{
private IChatMediator chatRoom;
private Player_3 Player_31;
private Player_3 Player_32;
private AI aiPlayer_3;
void Start()
{
chatRoom = new ChatRoom();
Player_31 = gameObject.AddComponent<Player_3>();
Player_31.SetName("Player_31");
Player_31.SetMediator(chatRoom);
Player_32 = gameObject.AddComponent<Player_3>();
Player_32.SetName("Player_32");
Player_32.SetMediator(chatRoom);
aiPlayer_3 = gameObject.AddComponent<AI>();
aiPlayer_3.SetName("AIPlayer_3");
aiPlayer_3.SetMediator(chatRoom);
chatRoom.AddMember(Player_31);
chatRoom.AddMember(Player_32);
chatRoom.AddMember(aiPlayer_3);
// 테스트 메시지 전송
Player_31.Send("Hello, everyone!");
aiPlayer_3.Send("Greetings, humans!");
}
}
ChatRoom 이라는 중재자를 두어 플레이어와 AI객체가 메시지를 주고받는 스크립트이다.
Player_31이 메시지를 보내면 Playyer_32와 aiPlayer에게 메시지가 전달되고 aiPlayer_3이 메시지를 보내면 Player_31과Player_32에게 메시지가 전달된다.
중재자 패턴을 사용하면 객체 간의 결합도를 낮추고 유연성을 높이는 장점이 있다. 직접 통신하는 것이 아닌 중재자와만 상호작용 하므로 객체간 많은 의존관계를 가져서 의존성이 높은 경우 사용하면 객체 간의 복잡한 연결 관리를 단순화 할 수 있다.
하지만 중재자가 모든 통신을 관리하기 때문에 중재자에 버그가 발생하면 전체 시스템에 영향이 간다는 단점이 있고 중재자가 너무 많은 책임을 가지게 되면 단일 책임 원칙(Single Responsibility Principle)를 위반할 수 있다.
'개인 공부 > 디자인패턴' 카테고리의 다른 글
| 유니티 반복자 (Iterator) (1) | 2024.07.19 |
|---|---|
| 유니티 전략 패턴 (Strategy) (0) | 2024.07.19 |
| 유니티 메멘토 (1) | 2024.07.19 |
| 유니티 옵저버 (1) | 2024.07.19 |
| 유니티 FSM (0) | 2024.07.17 |