Chapter 16. Mediator : 상대는 하나뿐

sua·2022년 4월 9일
0
post-thumbnail

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");
    }
}
profile
가보자고

0개의 댓글

관련 채용 정보