[디자인 패턴] 08. Mediator 패턴

다나·2023년 9월 25일
0

디자인 패턴

목록 보기
8/8

PART 1. Mediator 패턴 다이어그램

Mediator 패턴은 멤버(Colleague)들이 Medaiator 조정자이자 중재자에게 이야기를 하고, 중재자만이 멤버에게 지시를 내리는 패턴입니다.

예를 들어서, 관제탑을 생각했을 때 여러 비행기의 조종사가 대화하지 않고 관제탑과 이야기를 하는 것과 유사하다고 생각할 수 있습니다.

따라서 위의 패턴 다이어그램에서 볼 수 있듯이 여러 Colleague가 있고 서로 이야기하지 않고 Mediator와 연결되어 있음을 알 수 있습니다.

Colleague 쪽에서는 Mediator를 설정(setMediator)해줘야 하고, Mediator는 Colleauge들을 설정(생성)(createColleagues)해줘야 합니다.

colleagueChanged는 Colleague들이 Mediator에게 이야기를 하는 메소드이고, controlColleague는 Mediator가 내린 지시를 따르는 과정입니다.

즉, N:M 관계를 N:1 관계로 바꾸어줍니다.
(이때, 1은 Mediator, N은 Colleague입니다.)

하지만 여기에서 혼동하지 말아야 할 점은 Colleague들은 서로 이야기를 하고 싶어한다는 점입니다.


그러면 Mediator는 언제 사용될까요??

주로 다수의 객체 사이에서 조정해야 할 때 사용됩니다.

Mediator 패턴은 단순화하다라는 챕터에 있습니다.

이처럼 Colleague들이 서로 조정해야 하는 복잡한 상황에서 Mediator를 통해서 소통하도록 단순화할 수 있음을 의미합니다.

public interface Mediator {
	public abstract void createColleagues();
	public abstract void colleagueChanged();
}
public interface Colleague {
	public abstract void setMediator(Mediator mediator);
	public abstract void setColleagueEnabled(boolean enabled);
}
public class ConcreteColleague1 implements Colleague {
	private Mediator mediator;
	
	public ConcreteColleague1() {}

	@Override     // Mediator를 설정한다.
	public void setMediator(Mediator mediator) {
		this.mediator = mediator;
	}

	@Override     // Mediator에서 지시한다.
	public void setColleagueEnabled(boolean enabled) {
		setEnabled(enabled);
	}
}
public class ConcreteColleague2 implements Colleague {
	private Mediator mediator;
	
	public ConcreteColleague2() {}

	@Override 	// Mediator를 설정한다.
	public void setMediator(Mediator mediator) {
		this.mediator = mediator;
	}

	@Override 	// Mediator에서 지시한다.
	public void setColleagueEnabled(boolean enabled) {
		setEnabled(enabled);
	}

	@Override
	public void textValueChanged(TextEvent e) {
		// 문자열이 바뀌면 Mediator에 알린다.
		mediator.colleagueChanged();
	}
}
public class ConcreteMediator implements Mediator {
	private ConcreteColleague1 colleague1;
	private ConcreteColleague2 colleague2;

	public ConcreteMediator() {
		createColleagues();
		colleagueChanged(); // Colleague 생성
	}

	@Override
	public void createColleagues() { 
		//Colleague를 생성한다. (Mediator가 관리할 멤버를 생성) 
		colleague1 = new ConcreteColleague1();
		colleague2 = new ConcreteColleague2();

		// Mediator 설정
		colleague1.setMediator(this);
		colleague2.setMediator(this);
	}

	@Override
	public void colleagueChanged() {
		if(colleague1.getState()) {
			colleague2.setColleagueEnabled(false);
		} else { 
			colleague2.setColleagueEnabled(true);
		}
	}
}

ConcreteMediator에서 가장 주목해야 할 부분은 colleagueChanged입니다!

여기에서는 ConcreteColleague들이 서로 통신해야 하는 부분을 Mediator에서 파악하고 지시를 내리는 부분이기 때문입니다.

지금은 ConcreteColleague가 2개라서 복잡해보이지는 않지만 ConcreteColleague 클래스가 늘어날 수록 colleagueChanged 메소드의 처리 부분이 늘어나서 더 복잡한 처리를 수행해줄 수 있습니다.

아래의 시퀀스 다이어그램에서도 확인할 수 있듯이 ConcreteMediator에게 ConcreColleague가 이야기하고 지시를 내리는 부분을 확인할 수 있습니다.

하지만 ConcreteColleague1은 특정한 상황에 의존하는 코드가 없어서 다른 클래스에서 재사용하기 쉽지만, ConcreteMediator는 if, else 문과 같이 특정한 상황을 처리하고 대처하는 코드가 작성되어 있어서 재사용하기 어렵고 애플리케이션에 대한 의존성이 높다고 할 수 있습니다.


PART 2. 높은 Coupling 줄이기

PART 1에서 Mediator 패턴은 N:M의 관계를 N:1 관계로 바꿔주는 패턴이라고 이야기를 했습니다.

그러면 N:M 관계이면 어떠한 문제가 발생할까요??

바로, 높은 Coupling이 발생한다는 점입니다.

높은 Coupling은 서로 서로를 의존하기 때문에 다른 한개가 바뀌면 다른 것도 영향을 크게 받습니다.

여러 프로그램에서는 높은 coupling 같은 경우 complie이 안되는 경우도 있습니다.

따라서 Spring에서는 DI 의존성 주입을 통해서 이러한 Coupling을 낮추고 있습니다.

이때, DI 의존성 주입 방법으로 setter 주입이 있습니다.

이처럼 Mediator 패턴에서도 setMediator라는 메소드를 통해서 ConcreteColleauge들과 Mediator를 연결하여 Coupling을 낮출 수 있습니다.

public class ConcreteColleague1 implements Colleague {
	private Mediator mediator;
	
	public ConcreteColleague1() {}

	@Override     // Mediator를 설정한다.
	public void setMediator(Mediator mediator) {
		this.mediator = mediator;
	}

	@Override     // Mediator에서 지시한다.
	public void setColleagueEnabled(boolean enabled) {
		setEnabled(enabled);
	}
}
profile
컴퓨터공학과 학생이며, 백엔드 개발자입니다🐰

0개의 댓글