본문 바로가기

Design Pattern

[Java-Pattern] Mediator

 

조정자 역할을 하는 클래스를 뜻한다. 여러 클래스들이 서로 연관되어서 통신을 하게 될 경우

A,B 두개의 클래스라면 2개,A,B,C라면 6개..등등 클래스가 하나하나 늘어날때마다 제어해줘야하는

통신량은 어마어마하게 늘어나게 된다.


예를 들어 로그인 창을 하나 만든다고 할때, guest를 클릭하면 입력필드가 disable되고, login을 클릭하면 입력필드가 enable되면서 버튼이 생기고 이런 서로 연관된 동작을 가운데 중재자를 두어

통제하는 패턴 방식이다.


예제는 위에서 얘기한 로그인 애플릿 창이다.

등장 클래스..


1.Mediator - 카운셀러의 인터페이스를 정하는 인터페이스

2.Colleague - 멤버의 인터페이스를 정하는 인터페이스

3.ColleagueButton - 버튼을 나타내는 클래스

4.ColleagueTextField - 텍스트를 입력하는 클래스

5.ColleagueCheckBox - 첵크박스를 나타내는 클래스

6.LoginFrame - Mediator 인터페이스를 구현 , 로그인 다이얼로그를 나타내는 클래스


Mediator Interface

public interface Mediator {
    public abstract void createColleagues();
    public abstract void colleagueChanged(Colleague colleague);
}

createColleagues 메소드는 Mediator가 관리하는 멤버를 생성한다.

colleagueChanged는 상태가 변한 멤버들이 다음 자신의 행동을 결정하기 위해 호출하는

메소드이다. 인자는 자기 자신을 넘긴다.



Colleague Interface

public interface Colleague {
    public abstract void setMediator(Mediator mediator);
    public abstract void setColleagueEnabled(boolean enabled);
}

setMediator는 누구에게 자신의 다음 동작을 물어보면 될지 저장해두는 메소드이다.

setColleagueEnabled메소드는 카운셀러가 내리는 지시에 해당한다.



ColleagueButton클래스

import java.awt.Button;

public class ColleagueButton extends Button implements Colleague {
    private Mediator mediator;
    public ColleagueButton(String caption) {
        super(caption);
    }
    public void setMediator(Mediator mediator) {            // Mediator를 보관
        this.mediator = mediator;
    }
    public void setColleagueEnabled(boolean enabled) {      // Mediator가 유효/무효를 지시한다.
        setEnabled(enabled);
    }
}
setMediator를 이용해 카운셀러를 지정하고 있으며, 버튼은 스스로의 상태가 변한다기 보다는 체크박스나 텍스트필드의 변화에 의해 그 값이 바뀌기 때문에 카운셀러에게 물어보는 colleagueChanged메소드가 존재하지 않는다.


ColleagueTextField Class

import java.awt.TextField;
import java.awt.Color;
import java.awt.event.TextListener;
import java.awt.event.TextEvent;

public class ColleagueTextField extends TextField implements TextListener, Colleague {
    private Mediator mediator;
    public ColleagueTextField(String text, int columns) {   // 생성자
        super(text, columns);
    }
    public void setMediator(Mediator mediator) {            // Mediator를 보관
        this.mediator = mediator;
    }
    public void setColleagueEnabled(boolean enabled) {      // Mediator가 유효/무효를 지시한다.
        setEnabled(enabled);
        setBackground(enabled ? Color.white : Color.lightGray);
    }
    public void textValueChanged(TextEvent e) {             // 문자열이 변하면 Mediator에게 통지
        mediator.colleagueChanged(this);
    }
}

ColleagueCheckbox 클래스와 대동소이하며


public void textValueChanged(TextEvent e) {

   mediator.colleagueChanged(this);
    }
를 보면 텍스트필드에 어떤 이벤트가 발생할때마다 catch하여 그때마다 자기가 가지고 있는 카운셀러(mediator)에게 자신의 다음 상태를 물어보고 있다.



즉 동작의 프로세스를 보면 , LoginFrame에서는 각 멤버들을 생성시키고 그리고 그 멤버들의 setMediator메소드를 사용해 카운셀러를 지정한다. (여기서는 LoginFrame이 Mediator를 구현하여 colleagueChanged등의 메소드를 구현하고 있으므로 자기 자신을 카운셀러로 넘기게 되고, 이에 따라 각 멤버들인 자신에게 이벤트가 일어날때마다 LoginFrame이 가지고 있는 colleagueChanged메소드를 호출하게 된다.


 public void colleagueChanged(Colleague c) {
        if (c == checkGuest || c == checkLogin) {
            if (checkGuest.getState()) {             // Guest 모드
                textUser.setColleagueEnabled(false);
                textPass.setColleagueEnabled(false);
                buttonOk.setColleagueEnabled(true);
            } else {                                 // Login 모드
                textUser.setColleagueEnabled(true);
                userpassChanged();
            }
        } else if (c == textUser || c == textPass) {
            userpassChanged();
        } else {
            System.out.println("colleagueChanged:unknown colleague = " + c);
        }
    }

이런식으로 colleagueChanged메소드에서는 각 상태값을 체크하여 각각의 멤버에게 다음 상태값을 지정하여 준다. (setColleagueEnabled메소드)