안녕하세요! GoF 디자인 패턴 연재, 이번 시간에는 행위 패턴(Behavioral Patterns)의 한 종류로, 여러 객체 간의 복잡한 상호작용(M-to-M 관계)을 하나의 중재자 객체에 캡슐화하여 관리하는 중재자(Mediator) 패턴에 대해 알아보겠습니다.


정의

중재자 패턴시스템에 존재하는 다수의 객체(Colleague)들 간의 복잡한 상호작용을 중재자(Mediator)라는 하나의 객체에 집중하여 처리하도록 만드는 패턴입니다. 객체들은 더 이상 서로를 직접 참조하지 않고, 오직 중재자를 통해서만 소통합니다.

항공 관제탑을 생각하면 가장 이해하기 쉽습니다.

  • 수많은 비행기(Colleague 객체들)들이 공항에 착륙하거나 이륙하기 위해 서로의 위치, 속도, 경로를 파악해야 한다면 매우 복잡하고 위험할 것입니다. 모든 비행기가 다른 모든 비행기와 직접 통신해야 하니까요.
  • 하지만 항공 관제탑(Mediator 객체)이 있으면, 모든 비행기는 관제탑하고만 통신하면 됩니다. 관제탑은 모든 비행기의 정보를 종합하여 각 비행기에게 착륙 허가, 경로 변경 등의 지시를 내립니다.

이처럼 중재자 패턴은 객체들 간의 직접적인 연결(거미줄 같은 M-to-M 관계)을, 중재자를 통한 간접적인 연결(성형(Star) 구조의 1-to-M 관계)로 바꾸어 시스템의 복잡도를 낮추고 결합도를 줄여줍니다.

 

중재자(Mediator)와 동료(Colleague)가 중심이 되어 다음과 같은 구성요소를 가집니다.

  • Mediator (중재자): Colleague 객체들과 통신하기 위한 인터페이스를 정의합니다.
  • ConcreteMediator (구체적인 중재자): Mediator 인터페이스를 구현하며, 모든 Colleague 객체들을 알고 있습니다. Colleague들 간의 통신을 조정하고 중재하는 역할을 합니다.
  • Colleague (동료): 다른 Colleague와 통신해야 하는 객체들의 인터페이스입니다. Mediator 객체에 대한 참조를 가집니다.
  • ConcreteColleague (구체적인 동료): Colleague 인터페이스를 구현합니다. 자신의 상태가 변하거나 다른 Colleague에게 메시지를 보내야 할 때, Mediator에게 알립니다.

사용예시

여러 사용자가 참여하는 채팅방 시스템을 중재자 패턴으로 구현해 보겠습니다.

1. 중재자 (Mediator) 및 동료 (Colleague) 인터페이스/추상 클래스 정의

먼저 채팅방(중재자)과 사용자(동료)의 기반이 될 인터페이스와 추상 클래스를 정의합니다.

// Mediator 인터페이스
interface ChatMediator {
    void sendMessage(String msg, User user);
    void addUser(User user);
}

// Colleague 추상 클래스
abstract class User {
    protected ChatMediator mediator;
    protected String name;

    public User(ChatMediator med, String name){
        this.mediator = med;
        this.name = name;
    }

    public abstract void send(String msg);
    public abstract void receive(String msg);
}

2. 구체적인 중재자 (ConcreteMediator) 클래스 구현

실제 채팅방의 역할을 하는 ChatRoom 클래스를 구현합니다.

import java.util.ArrayList;
import java.util.List;

// ConcreteMediator 클래스
public class ChatRoom implements ChatMediator {
    private List<User> users;

    public ChatRoom(){
        this.users = new ArrayList<>();
    }

    @Override
    public void addUser(User user){
        this.users.add(user);
    }

    @Override
    public void sendMessage(String msg, User user) {
        // 메시지를 보낸 사용자를 제외한 모든 사용자에게 메시지 전송
        for(User u : this.users){
            if(u != user){
                u.receive(msg);
            }
        }
    }
}

3. 구체적인 동료 (ConcreteColleague) 클래스 구현

채팅에 참여하는 실제 사용자를 구현합니다.

// ConcreteColleague 클래스
public class ChatUser extends User {

    public ChatUser(ChatMediator med, String name) {
        super(med, name);
    }

    @Override
    public void send(String msg){
        System.out.println(this.name + ": Sending Message = " + msg);
        mediator.sendMessage(msg, this);
    }
    
    @Override
    public void receive(String msg) {
        System.out.println(this.name + ": Received Message: " + msg);
    }
}

4. 클라이언트 (Client) 코드

클라이언트는 중재자와 동료 객체들을 생성하고 연결합니다.

public class ChatClient {
    public static void main(String[] args) {
        // 1. 중재자(채팅방) 생성
        ChatMediator mediator = new ChatRoom();
        
        // 2. 동료(사용자)들 생성 및 채팅방에 추가
        User user1 = new ChatUser(mediator, "Alice");
        User user2 = new ChatUser(mediator, "Bob");
        User user3 = new ChatUser(mediator, "Charlie");
        
        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);
        
        // 3. 사용자가 메시지 전송
        user1.send("안녕하세요!");
        
        // 실행 결과:
        // Alice: Sending Message = 안녕하세요!
        // Bob: Received Message: 안녕하세요!
        // Charlie: Received Message: 안녕하세요!
    }
}

 


결론

중재자 패턴은 1:M관계를 단순화하는 효율적인 패턴으로 다음과 같은 경우에 사용됩니다.

  • 다수의 객체들이 서로 복잡하게 통신하여 결합도가 너무 높아질 때: 객체 간의 직접적인 연결을 없애고 중재자를 통해 통신하게 함으로써 결합도를 낮출 수 있습니다.
  • 한 객체의 변경이 다른 많은 객체들의 변경을 초래하는 경우: 중재자를 사용하면 각 `Colleague`는 독립적으로 변경할 수 있고, 통신 방식의 변경은 `Mediator`만 수정하면 됩니다.
  • 재사용하기 어려운 객체를 상속 대신 중재자를 통해 재사용하고 싶을 때

그러나, 모든 통신이 중재자에 집중되므로, 시스템이 복잡해질수록 중재자 객체 자체가 매우 복잡해지고 거대해질 수 있습니다. (God Object 안티 패턴)

중재자 패턴은 복잡한 객체 관계망을 단순하고 관리하기 쉬운 구조로 만들어주는 효과적인 방법입니다. 객체 간의 상호작용 로직을 한 곳에 모아 응집도를 높이고, 각 객체는 자신의 역할에만 충실하게 만들어줍니다. 다음시간에는 Memento 패턴에 대해서(메멘토 MOOORI) 알아보겠습니다!

+ Recent posts