17.    The Mediator Pattern

어떤 프로그램이 여러 개의 클래스로 만들어져 있을 때 로직과 계산은 이러한 클래스로부터 논리적으로 나뉘어 진다.그러나 이러한 고립적인 클래스들이 증가함에 따라 이러한 클래스들의 통신 문제가 보다 복잡해졌다.다른 클래스의 메소드들에 대하여 아는 것이 필요한 클래스가 더 많아지고 클래스들의 구조는 더 얽혀 복잡해 진다.이것이 프로그램을 읽는 것과 유지를 어렵게 한다.게다가 프로그램을 변경하는 것이 어려운데 왜냐면 어떤 변화가 여러 개의 다른 클래스들에서 코드에 영향을 줄 지도 모르기 때문이다. Mediator패턴은 이러한 클래스들 사이의 느슨한 커플링을 진행하여 이러한 문제를 해결할 수 있는 방법을 소개한다.Mediator는 다른 클래스들의 메소드들에 대한 정보를 설명한 오직 하나의 클래스의 이용하여 이 문제를 해결할 수 있다.클래스들은 변경되었을 때mediator에게 정보를 준고Mediator는 정보를 필요로 하는 다른 클래스들에게 정보를 전달해 준다.

 

구조

사용자 삽입 이미지

 

역할

  • Mediator – Colleague역할과 통신을 해서 조정을 하기 위한 인터페이스(API)를 정하는 역할을 한다.
  • ConcreteMediator – Mediator역할의 인터페이스(API)를 구현하여 실제의 조정을 수행 하는 역할을 한다.
  • Colleague – Mediator역할과 통신을 할 인터페이스(API)를 정합니다.
  • Concretecolleague – Colleague역할의 인터페이스(API)를 구현합니다.

 

의도

다수의 객체를 조정해야 하는 경우Mediator패턴을 사용합니다.

 

적용시기

  • 어떤 객체들의 집합이 잘 정의되었지만,복잡한 방법으로 통신할 때.
  • 어떤 객체를 재사용하는 것이 그것이 많은 다른 객체들과 관련이 있고 통신을 하기 때문에 어려울 때.
  • 몇몇의 클래스들 사이에 분산되어진 하나의 행위가 많은subclassing하는 작업 없이customize되어져야 할 때.

결론

l        Mediator는 한 개의 클래스에서 일어나는 액션이 다른 상태에 반영되어야 할 경우 클래스들이 복잡해지는 것을 막는다.

l        Mediator는 프로그램의 작동을 쉽게 한다.많이 변경할 경우 단지Mediator를 변경하거나 서브클래스로 분류한다.그리고 나머지 프로그램은 변경하지 않은 상태로 둔다.

l        새로운 컨트롤이나 다른 클래스들이Mediator를 제외한 어떤 것도 변경하지 않고 추가할 수 있다.

l        Mediator는 객체와 나머지 사용자 인터페이스에 있는 메소드에 대해서 모두 알고 있어야 하는 각각의command객체의 문제를 해결한다.

l        가끔Mediator는 프로그램에 대해 너무 많은 지식을 갖는‘god클래스가 될수 있는데,이것은Mediator를 변경하고 유지하게 어렵게 만든다.개별적 클래스에 좀더 많은 기능을 추가하고, Mediator에는 기능을 줄여서 이러한 상황을 개선할 수 있다.각각의 객체는 자신의 업무를 샐행한다.그리고Mediator는 객체들 간의 상호 작용을 관리한다.

l        각각의Mediator는 호출하기 위해서 각각의colleague의 메소드를 가지는데,이것은Colleague마다 가지고 있는 메소드가 유용한지를 아는 맞춤형 쓰기 클래스이다.이것은 다른 프로젝트에서 사용한Mediator코드를 다시 하용하는 것을 어렵게 한다.그러나 대부분의Mediator는 아주 간단하며,이 코드를 사용하는 것이 다른 방법으로 복잡한 객체 상호 작용을 관리하는 것보다 훨씬 쉽다.

 

구현상의 문제

Mediator는 가장 일반적인 패턴이지만,비주얼 인터페이스 프로그램에서 매우 폭넓게 사용된다.다중 객체들 간의 복잡한 상호 의사 소통을 해결해야 하는 문제에 직면할 때마다Mediator를 사용할 수 있다.

 

예제소스

사용자 삽입 이미지

이 프로그램은 왼쪽에(50free.txt)파일에 등록된 모든 아이들을 표시하고,클럽 리스트로 콤보 박스를 체운다.그런 다음 사용자가 클럽을 선택하면 우측리스트에는 클럽에 소속된 아이들만 표시한다.

 

예제 소스

public interface Mediator {

   public abstract void createColleagues();

   public abstract void colleagueChanged(Colleague colleague);

}

 

public interface Colleague {

   public abstract void setMediator(Mediator mediator);

   public abstract void setColleagueEnabled(boolean enabled);

}

 

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) {

       this.mediator = mediator;

   }

   

   public void setColleagueEnabled(boolean enabled) {

       setEnabled(enabled);

   }

}

 

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) {

       this.mediator = mediator;

   }

   

   public void setColleagueEnabled(boolean enabled) {

       setEnabled(enabled);

   }

   

   public void itemStateChanged(ItemEvent e) {

       mediator.colleagueChanged(this);

   }

}

 

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) {

       this.mediator = mediator;

   }

   

   public void setColleagueEnabled(boolean enabled) {

       setEnabled(enabled);

       setBackground(enabled ? Color.white : Color.lightGray);

   }

   

   public void textValueChanged(TextEvent e) {

       mediator.colleagueChanged(this);

   }

}

 

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;

 

   public LoginFrame(String title) {

       super(title);

       setBackground(Color.lightGray);

       setLayout(new GridLayout(4, 2));

       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();

   }

 

   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");

       checkGuest.setMediator(this);

       checkLogin.setMediator(this);

       textUser.setMediator(this);

       textPass.setMediator(this);

       buttonOk.setMediator(this);

       buttonCancel.setMediator(this);

       checkGuest.addItemListener(checkGuest);

       checkLogin.addItemListener(checkLogin);

       textUser.addTextListener(textUser);

       textPass.addTextListener(textPass);

       buttonOk.addActionListener(this);

       buttonCancel.addActionListener(this);

   }

 

   public void colleagueChanged(Colleague c) {

       if (c == checkGuest || c == checkLogin) {

           if (checkGuest.getState()) {

               textUser.setColleagueEnabled(false);

               textPass.setColleagueEnabled(false);

               buttonOk.setColleagueEnabled(true);

           } else {

               textUser.setColleagueEnabled(true);

               userpassChanged();

           }

       } else if (c == textUser || c == textPass) {

           userpassChanged();

       } else {

           System.out.println("colleagueChanged:unknown colleague = " + c);

       }

   }

 

   private void userpassChanged() {

       if (textUser.getText().length() > 0) {

           textPass.setColleagueEnabled(true);

           if (textPass.getText().length() > 0) {

               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);

   }

}

 

public classMain{

   static public void main(String args[]) {

       new LoginFrame("Mediator패턴Demo");

   }

}

사용자 삽입 이미지

 

관련패턴

  • Façade Pattern – Mediator패턴에서Mediator역할은Colleague역할의 중개자로서 주고 받기를 수행합니다. Façade패턴에서는Façade역할이 일방적으로 다른 역할을 이용해서 높은 레벨의 인터페이스(API)를 만듭니다. Mediator가 양방향이지만, Façade는 단 방향이라고 말할 수 있습니다.
  • Observer Pattern – Mediator역할과Colleague역할의 통신은Observer패턴을 사용하여 수행되는 경우가 있습니다.

 

'Programming > Design Pattern' 카테고리의 다른 글

[펌] The Interpreter Pattern  (0) 2006.01.21
[펌] The Iterator Pattern  (0) 2006.01.21
[펌] The Memento Pattern  (0) 2006.01.21
[펌] The Interpreter Pattern  (0) 2006.01.21
[펌] The Iterator Pattern  (0) 2006.01.21

Posted by 영웅기삼
,