1. 예제 프로그램
<Mediator.java>
package ch16.Sample;
// ‘카운셀러’를 표현하는 인터페이스
public interface Mediator {
// mediator가 관리하는 멤버를 생성하는 메소드
public abstract void createColleagues();
// 각 멤버가 ‘상담’을 요청할 때 호출하는 메소드
// 라디오 버튼이나 텍스트 필드의 상태가 변화했을 때, 이 메소드가 호출된다.
public abstract void colleagueChanged(Colleague colleague); //상담을 요청한 멤버가 인자로 들어감
}
<Colleague.java>
package ch16.Sample;
//‘카운셀러’에게 상담하러 오는 멤버를 나타내는 인터페이스
public interface Colleague {
// 중재자 설정 메소드
// Mediator 인터페이스를 구현한 LoginFrame 클래스가 첫번째로 호출하는 메소드
// “내가 카운셀러니까 기억해두세요”라는 의미
public abstract void setMediator(Mediator mediator);
// “카운셀러가 내리는 지시”에 해당함
// 멤버의 상태를 “유효” 또는 “무효”로 바꾸는 일을 수행한다.
public abstract void setColleagueEnabled(boolean enabled);
}
<ColleagueButton.java>
package ch16.Sample;
import java.awt.Button;
public class ColleagueButton extends Button implements Colleague {
private Mediator mediator;
public ColleagueButton(String caption) {
super(caption);
}
// 입력 인자로 들어온 Mediator를 멤버 변수인 mediator에 할당함
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
// Button 클래스에서 물려받은 setEnabled(boolean)를 호출하여 유효/무효를 설정한다.
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled); // setEnabled( )는 부모인 Button 클래스로부터 물려받은 메소드이다.
}
}
<ColleagueTextField.java>
package ch16.Sample;
import java.awt.TextField;
import java.awt.Color;
import java.awt.event.TextListener;
import java.awt.event.TextEvent;
// java.awt.event.TextListener 인터페이스도 구현함
// 텍스트 필드의 내용이 바뀌었을 때, TextEvent를 처리하는 textValueChanged 메소드를 제공한다.
public class ColleagueTextField extends TextField implements TextListener, Colleague {
private Mediator mediator;
public ColleagueTextField(String text, int columns) { // 생성자
super(text, columns);
}
// 입력 인자로 들어온 Mediator를 멤버 변수인 mediator에 할당함
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
// TextFiled 클래스에서 물려받은 setEnabled(boolean)를 호출하여 유효/무효를 설정한다.
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
// enabled가 true이면, 배경색을 흰색으로, enabled가 false이면 배경색을 회색으로 칠한다.
// white, ligthGray: Color 클래스에 선언되어 있는 상수
setBackground(enabled ? Color.white : Color.lightGray);
}
// TextListener 인터페이스에 정의되어 있는 메소드
// TextField의 값이 바뀔 때마다, TextEvent가 발생되고, 이 메소드가 자동으로 호출된다.
public void textValueChanged(TextEvent e) {
mediator.colleagueChanged(this); // 문자열이 변하면 Mediator에게 통지한다.
}
}
<ColleagueCheckbox.java>
package ch16.Sample;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
public class ColleagueCheckbox extends Checkbox implements ItemListener,
Colleague {
private Mediator mediator;
public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) { // 생성자
super(caption, group, state);
}
public void setMediator(Mediator mediator) { // Mediator를 보관
this.mediator = mediator;
}
// “카운셀러가 내리는 지시”에 해당함
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
}
// 라디오버튼의 상태가 바뀌었을 때, ItemEvent가 발생되고,
// 등록된 ItemListener의 이 메소드가 자동으로 호출된다.
public void itemStateChanged(ItemEvent e) {
mediator.colleagueChanged(this); // 상태가 변하면 Mediator에게 통지한다.
}
}
<LoginFrame.java>
package ch16.Sample;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Color;
import java.awt.CheckboxGroup;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
// 중재자 역할을 하는 클래스
public class LoginFrame extends Frame implements ActionListener, Mediator {
private ColleagueCheckbox checkGuest;
private ColleagueCheckbox checkLogin;
private ColleagueTextField textUser;
private ColleagueTextField textPass;
private ColleagueButton buttonOk;
private ColleagueButton buttonCancel;
// 생성자
// Colleague들을 생성해서 배치한 후에 표시를 실행한다.
public LoginFrame(String title) {
super(title);
// 배경색의 설정(setBackground( ) 이용)
setBackground(Color.lightGray);
// 레이아웃 매니저: 프레임을 구성하는 구성 요소의 배치를 결정한다.
// 그리드 레이아웃 매니저를 사용해서 4*2의 그리드를 만든다.
// 즉, 프레임 영역을 4행 2열로 나눔
setLayout(new GridLayout(4, 2));
// Colleague들의 생성
createColleagues();
// 생성된 Colleague들을 배치
add(checkGuest);
add(checkLogin);
add(new Label("Username:"));
add(textUser);
add(new Label("Password:"));
add(textPass);
add(buttonOk);
add(buttonCancel);
// 각 체크박스 유효/무효를 초기화한다.
colleagueChanged(checkGuest);
// 표시
pack(); // 포함된 컴포넌트들의 레이아웃(배치 상태)에 맞게 윈도우 크기를 조정한다.
show(); // 윈도우를 보여준다.
}
// Colleague들을 생성한다.
public void createColleagues() {
// 생성
// Checkbox 생성
CheckboxGroup g = new CheckboxGroup();
checkGuest = new ColleagueCheckbox("Guest", g, true);
checkLogin = new ColleagueCheckbox("Login", g, false);
textUser = new ColleagueTextField("", 10);
textPass = new ColleagueTextField("", 10);
textPass.setEchoChar('*'); //텍스트가 별표로 보이게
buttonOk = new ColleagueButton("OK");
buttonCancel = new ColleagueButton("Cancel");
// Mediator를 설정한다. 각 GUI 컴포넌트의 중재자는 현재 클래스 자신이다.
checkGuest.setMediator(this); //this라는 것은 현재의 객체가 중재자 역할을 한다는 것
checkLogin.setMediator(this);
textUser.setMediator(this);
textPass.setMediator(this);
buttonOk.setMediator(this);
buttonCancel.setMediator(this);
// Listener들을 설정한다.
checkGuest.addItemListener(checkGuest); // 자신이 이벤트 리스너가 된다
checkLogin.addItemListener(checkLogin); // 자신이 이벤트 리스너가 된다
textUser.addTextListener(textUser); // 자신이 이벤트 리스너가 된다
textPass.addTextListener(textPass); // 자신이 이벤트 리스너가 된다
buttonOk.addActionListener(this);
buttonCancel.addActionListener(this);
}
// colleague의 상태가 변화했을 때, 호출되는 메소드
// Colleague로부터의 통지가 오면, 통지의 종류를 파악하여 각 Colleague의 유효/무효를 판정한다.
// colleague의 상태 변화에 따라 해당 colleague의 상태를
// 어떻게 변화시킬 것인가에 대한 로직을 가지고 있다.
public void colleagueChanged(Colleague c) {
// 상태변화가 발생한 곳이 checkGuest나 checkLogin이면...
if (c == checkGuest || c == checkLogin) {
if (checkGuest.getState()) { // checkGuest가 체크되었다면...
textUser.setColleagueEnabled(false);
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(true);
} else { // checkLogin이 체크되었다면...
textUser.setColleagueEnabled(true);
userpassChanged(); // user name 이나 password 텍스트필드가 바뀐 것이므로...
}
}
// 상태변화가 발생한 곳이 textUser나 textPass이면...
else if (c == textUser || c == textPass) {
userpassChanged();
} else {
System.out.println("colleagueChanged:unknown colleague = " + c);
}
}
// TextField 상태 변화에 따라 버튼 활성화/비활성화한다.
private void userpassChanged() {
if (textUser.getText().length() > 0) { // textUser에 값이 들어가 있다면...
textPass.setColleagueEnabled(true); // textPass를 유효화 시킨다.
if (textPass.getText().length() > 0) { // textPass에 값이 들어가 있다면...
buttonOk.setColleagueEnabled(true); // buttonOk를 유효화시킨다.
} else {
buttonOk.setColleagueEnabled(false); // textPass에 값이 들어가 있지 않다면...
}
} else { // textUser에 값이 들어가 있지 않다면... textPass와 buttonOk를 무효화시킨다.
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(false);
}
}
// OK, Cancel 버튼이 눌러졌을 때 실행되는 메소드
public void actionPerformed(ActionEvent e) { // 버튼이 눌려지면
System.out.println("" + e); // 발생된 이벤트에 대한 설명을 화면에 출력하고
System.exit(0); // 프로그램을 종료한다.
}
}
<Main.java>
package ch16.Sample;
public class Main {
static public void main(String args[]) {
new LoginFrame("Mediator Sample"); // LoginFrame의 인스턴스를 생성함
}
}
2. 연습 문제 - 사용자 로그인 상태일 때, 사용자 명과 패스워드 둘 다 네문자 이상인 경우에만 OK버튼이 유효하도록
<Mediator.java>
package ch16.A1;
public interface Mediator {
public abstract void createColleagues();
public abstract void colleagueChanged(Colleague colleague);
}
<Colleague.java>
package ch16.A1;
public interface Colleague {
public abstract void setMediator(Mediator mediator);
public abstract void setColleagueEnabled(boolean enabled);
}
<ColleagueButton.java>
package ch16.A1;
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);
}
}
<ColleagueTextField.java>
package ch16.A1;
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.java>
package ch16.A1;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {
private Mediator mediator;
public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) { // 생성자
super(caption, group, state);
}
public void setMediator(Mediator mediator) { // Mediator를 보관
this.mediator = mediator;
}
public void setColleagueEnabled(boolean enabled) { // Mediator가 유효/무효를 지시한다.
setEnabled(enabled);
}
public void itemStateChanged(ItemEvent e) { // 상태가 변하면 Mediator에게 통지
mediator.colleagueChanged(this);
}
}
<LoginFrame.java>
package ch16.A1;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Color;
import java.awt.CheckboxGroup;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class LoginFrame extends Frame implements ActionListener, Mediator {
private ColleagueCheckbox checkGuest;
private ColleagueCheckbox checkLogin;
private ColleagueTextField textUser;
private ColleagueTextField textPass;
private ColleagueButton buttonOk;
private ColleagueButton buttonCancel;
// 생성자
// Colleague들을 생성해서 배치한 후에 표시를 실행한다.
public LoginFrame(String title) {
super(title);
setBackground(Color.lightGray);
// 레이아웃 매니저를 사용해서 4*2의 그리드를 만든다.
setLayout(new GridLayout(4, 2));
// Colleague들의 생성
createColleagues();
// 배치
add(checkGuest);
add(checkLogin);
add(new Label("Username:"));
add(textUser);
add(new Label("Password:"));
add(textPass);
add(buttonOk);
add(buttonCancel);
// 유효/무효의 초기 지정
colleagueChanged(checkGuest);
// 표시
pack();
show();
}
// Colleague들을 생성한다.
public void createColleagues() {
// 생성
CheckboxGroup g = new CheckboxGroup();
checkGuest = new ColleagueCheckbox("Guest", g, true);
checkLogin = new ColleagueCheckbox("Login", g, false);
textUser = new ColleagueTextField("", 10);
textPass = new ColleagueTextField("", 10);
textPass.setEchoChar('*');
buttonOk = new ColleagueButton("OK");
buttonCancel = new ColleagueButton("Cancel");
// Mediator의 세트
checkGuest.setMediator(this);
checkLogin.setMediator(this);
textUser.setMediator(this);
textPass.setMediator(this);
buttonOk.setMediator(this);
buttonCancel.setMediator(this);
// Listener의 세트
checkGuest.addItemListener(checkGuest);
checkLogin.addItemListener(checkLogin);
textUser.addTextListener(textUser);
textPass.addTextListener(textPass);
buttonOk.addActionListener(this);
buttonCancel.addActionListener(this);
}
// Colleague로부터의 통지로 각 Colleague의 유효/무효를 판정한다.
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);
}
}
// textUser 또는 textPass의 변경이 있었다.
// 각Colleague의 유효/무효를 판정한다.
private void userpassChanged() {
if (textUser.getText().length() > 0) {
textPass.setColleagueEnabled(true);
if (textUser.getText().length() >= 4 && textPass.getText().length() >= 4) {
buttonOk.setColleagueEnabled(true);
} else {
buttonOk.setColleagueEnabled(false);
}
} else {
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(false);
}
}
public void actionPerformed(ActionEvent e) {
System.out.println("" + e);
System.exit(0);
}
}
<Main.java>
package ch16.A1;
public class Main {
static public void main(String args[]) {
new LoginFrame("Mediator Sample");
}
}