티스토리 뷰

중재자 패턴이란?

중재자 패턴은 여러 객체들에게 분산될 행위를 한 곳(Mediator 객체)으로 모아줌으로써 객체들 간의 연결강도를 줄여줍니다. 이로써 객체들간의 관계를 M:N에서 M:1로 줄여주어서 각 객체들은 Mediator 객체를 제외한 다른 객체는 알지 못하고, 중재자 클래스에만 의존하게 됩니다.

 

 

중재자 패턴의 사용 방법

  • Mediator : Colleague 객체간의 커뮤니케이션을 위한 인터페이스 정의
  • Colleague : Mediator를 통해 다른 Colleague와 커뮤니케이션을 위한 인터페이스 정의
  • ConcreteMediator : Mediator 구현체로 Colleague들간의 상호 커뮤니케이션을 위해 Colleague들을 가지고 있으며 커뮤니케이션을 조정함
  • ConcreteColleague : Colleague 인터페이스 구현체
// Mediator.java (Mediator)
public interface Mediator {
    void addUser(User user);
    void removeUser(User user);
    void sendMessage(User user, String message);
}

// UserMessageMediator.java (ConcreteMediator)
public class UserMessageMediator implements Mediator {

    private List<User> userList = new ArrayList<>();

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

    @Override
    public void removeUser(User user) {
        userList.remove(user);
    }

    @Override
    public void sendMessage(User user, String message) {
        for (User u : userList) {
            if (u != user) {
                u.receive(message);
            }
        }
    }
    
}

// User.java (Colleague)
public abstract class User {
    protected Mediator mediator;
    protected String name;

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

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

// ManUser.java (ConcreteColleague)
public class ManUser extends User {

    public ManUser(Mediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    public void receive(String message) {
        System.out.println("[" + super.name + "] Message arrived: " + message);
    }

    @Override
    public void send(String message) {
        System.out.println("[" + super.name + "] Sent message");
        super.mediator.sendMessage(this, message);
    }
    
}

// WomanUser.java (ConcreteColleague)
public class WomanUser extends User {

    public WomanUser(Mediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    public void receive(String message) {
        System.out.println("[" + super.name + "] Message arrived: " + message);
    }

    @Override
    public void send(String message) {
        System.out.println("[" + super.name + "] Sent message");
        super.mediator.sendMessage(this, message);
    }
    
}

// Client.java (Client)
public class Client {
    public static void main(String[] args) {
        Mediator mediator = new UserMessageMediator();

        User user1 = new ManUser(mediator, "Sonny");
        User user2 = new ManUser(mediator, "Jimin");
        User user3 = new WomanUser(mediator, "Minji");
        User user4 = new WomanUser(mediator, "Jenny");
        
        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);
        mediator.addUser(user4);

        user1.send("어 나 프리미어리그 득점왕 손흥민인데");

        mediator.removeUser(user2);
        user3.send("어 나 뉴진스 민진데");
    }
}

패턴 사용 시기

  • 객체들간의 상호작용이 복잡해서 서로간의 의존관계가 구조화되어 있지 않고 이해하기 어려울 때
  • 하나의 객체가 많은 다른 객체들을 참조하고 있어 이것을 재사용하기 어려울 때
  • 여러 클래스에 분산되어 있는 행위를 많은 서브클래스없이 재구성해야 할 때

패턴 장점

  • 효율적인 자원 관리가 가능합니다.
  • 중재자 구현 클래스는 추후에 더 효율적인 클래스로 변경될 수 있습니다.
  • 객체들끼리 직접 참조하는 것을 피해 객체들 간의 연결강도를 줄입니다.

패턴 단점

  • 객체간의 통신 로직이 복잡해지거나 객체의 형태가 자주 변경되는 경우 유지보수 및 관리가 어렵습니다.

 


옵서버 패턴 vs 중재자 패턴

공통점: 1통신을 위해 인터페이스를 설계하고 제공한다는 점에서 두 패턴은 동일

차이점: 퍼사드 패턴은 단방향 통신만 가능하지만 중재자 패턴은 양방향 통신을 지원

퍼사드 패턴 vs 중재자 패턴

공통점: Publisher-Subscriber

차이점: 옵저버 패턴은 1개의 publisher에 대해 N개의 subscriber가 존재하고 observer가 pulling이나 push 방식을 통해 관리하지만 중재자 패턴은 M개의 publisher와 N개의 subscriber 사이에서 1개의 mediator를 통해 통신을 하는 방식