Mediator 패턴

5.디자인패턴 2016. 9. 18. 21:46

시스템을 설계하다 보면 이벤트가 발생하는 객체가 여러개(M)이고, 이들 이벤트를 받는 곳도 여러 곳(N)인 경우가 있다. 이런 경우에 모든 이벤트들을 주고 받기 위해서는 M : N의 관계가 생기게 된다. 이렇게 되면 전체 시스템이 복잡해지는 것은 당연하다. Mediator(중재자) 패턴은 이런 다 대 다 관계에 중간 객체를 도입하여 각각 일 대 다 관계를 만들어 주는 패턴이다.

우선 객체들 간의 관계가 아래와 같다고 하자.

각 이벤트 소스들은 모두 이벤트 수신자에게 이벤트를 보내 주어야 한다. 소스나 수신자의 개수가 1~2개 정도 일 경우에는 크게 문제가 없겠지만 그 개수가 늘어나게 되면 위와 같이 복잡한 관계가 만들어지게 된다. 이것은 모든 소스가 각각 모든 수신자들을 알고 있어야 하고, 자신이 알고 있는 모든 수신자에게 이벤트를 전달해 주기 때문이다. 이를 단순화 하기 위해서는 각 소스들은 각각 이벤트가 발생했다는 사실만 별도의 객체에 알려 주고, 이벤트 수신자에게 이벤트를 보내는 역할은 그 객체가 담당하도록 만들면 된다. 이것이 Mediator(중재자) 패턴이다.

위의 객체들 간의 관계를 중재자를 통해 단순화 하면 다음과 같다.

이처럼 소스와 수신자 간의 복잡한 관계를 단순화 시켜줄 수 있다.


Mediator 패턴 클래스 다이어그램


복잡한 관계를 단순화 하기 위해서는 소스와 수신자를 동일화 시킬 필요가 있다. 소스 측은 ISource 인터페이스를 통해서 구현하도록 만들고, 수신자 측은 IDestination 인터페이스를 구현하도록 한다. 그리고 소스 측 구체 클래스인 TcpComm과 SystemSignal을 만들어 주고, 수신자 측 구체 클래스는 Display와 Log를 각각 만들어 준다. 더 많은 소스와 수신자가 있을 때 Mediator가 더 유용해지지만, 복잡함을 피하기 위해서 각각 둘 씩 만 구현했다.

소스는 setMediator() 메소드를 통해서 외부로부터 Mediator 객체를 주입 받는다. 그리고 이벤트가 발생하면 Mediator 객체의 onEvent() 메소드를 호출하여 자신에게 발생한 이벤트를 전달해 주도록 한다. IDestination을 구현한 수신자 객체들은 생성된 후 Mediator 객체에 자신을 등록 시킨다. 이를 통해 Mediator 객체가 이벤트 발생 시 이벤트를 전달 받을 수신자들을 알 수 있게 된다.

아래는 Mediator 패턴의 구현이다.


Mediator 패턴의 구현

interface ISource{

    public void setMediator(Mediator mediator);

    public void eventOccured(String event);

}

class TcpComm implements ISource{

    Mediator mediator;

    public void setMediator(Mediator mediator){ // 중재자 설정

        this.mediator = mediator;

    }

   

    public void eventOccured(String event){ // 이벤트의 전달

        mediator.onEvent("TCP comm", event);

    }

}

class SystemSignal implements ISource{

    Mediator mediator;

    public void setMediator(Mediator mediator){ // 중재자 설정

        this.mediator = mediator;

    }

   

    public void eventOccured(String event){ // 이벤트의 전달

        mediator.onEvent("System", event);

    }

}

interface IDestination{

    public void receiveEvent(String from, String event);

}

class Display implements IDestination{

    public void receiveEvent(String from, String event){

        System.out.println("Display : from " + from + " event : " + event);

    }

}

class Log implements IDestination{

    public void receiveEvent(String from, String event){

        System.out.println("Log : from " + from + " event : " + event);

    }

}

class Mediator{

    List<IDestination> list = new ArrayList<IDestination>();

    public void addDestination(IDestination destination){ list.add(destination); }

   

    public void onEvent(String from, String event){

        for(IDestination each : list){ // 이벤트의 전송

            each.receiveEvent(from, event);

        }

    }

}


실행 방법

public static void main(String[] args) {

    Mediator mediator = new Mediator();

    ISource tcp = new TcpComm();

    tcp.setMediator(mediator);

    ISource system = new SystemSignal();

    system.setMediator(mediator);

    mediator.addDestination(new Display());

    mediator.addDestination(new Log());

    tcp.eventOccured("connected");

    tcp.eventOccured("disconnected");

    system.eventOccured("key input");

    system.eventOccured("mouse input");

} 

main() 메소드에서는 Mediator와 소스, 그리고 수신자를 생성하고, 각각의 관계를 설정해 준다. 이벤트는 소스에서 생성되어 중재자를 거쳐 수신자 쪽으로 흘러 가게 된다. 실행을 시켜 보면 어떤 소스로부터 이벤트가 발생하더라도 수신자들 모두에게 잘 전달됨을 알 수가 있다.

'5.디자인패턴' 카테고리의 다른 글

Actor Model 패턴의 구현(Java)  (0) 2016.09.30
Property List 패턴  (0) 2016.09.24
Facade 패턴  (0) 2016.09.18
Command 패턴  (0) 2016.09.18
Flyweight 패턴  (0) 2016.09.18
Posted by 이세영2
,