Java/Design Pattern

[디자인 패턴] 행동 패턴 - 중재자 패턴 (Mediator Pattern)

민돌v 2023. 4. 10. 10:27
728x90
(인프런) 코딩으로 학습하는 GoF의 디자인 패턴 - 백기선, 강의를 보고 정리한 글입니다.
코드는 GitHub 에 있습니다

 

#1. 객체 생성 관련 패턴

#2. 구조 관련 패턴

 

#3. 행동 관련 패턴

 

 

 


✔️ 중재자 패턴이란 (Mediator Patterns)

여러 객체들간의 의사소통하는 방법을 캡슐화하여 객체간의 의존성(결합도)를 낮추는 패턴
  • 마치 층간소음이 생겼을 때, 이웃과 직접 이야기하지 않고 관리사무소에 이야기하는 것처럼 (?) 객체간의 중간 의사소통 담당자 (중재자)를 통해 객체간의 소통을 캡슐화하는 방법입니다.
  • 아래의 다이어그램은 중재자 패턴의 한 종류 입니다.
    • 모든 Collegue (컴포넌트 or 객체) 들은 각각의 Mediator 를 참조하고 있습니다.
    • 각각의 Collegue 는 서로서로를 참조 하지 않습니다.
    • 각각으 Collegue 들은 Mediator 를 통해서만 서로를 찾아갑니다.

 

 

중재자 패턴 구조

  • Mediator: Colleague 객체 간의 상호참조를 위한 인터페이스. 클라이언트 등록, 실행 등의 메소드 정의
  • Colleague: 다른 Colleague와의 상호참조를 위한 인터페이스.
  • ConcreteMediator: Mediator 구현 클래스. Colleague 간의 상호참조를 조정
  • ConcreteColleage: Colleague 구현 클래스. Mediator를 통해 다른 Colleague와의 상호참조

 


✔️ 중재자 패턴 사용 예시

위의 다이어그램은, Collegue(특정한 기능 클래스) 의 상속과 Mediator 의 위임을 통한 참조구조를 띄우고 있지만
강의 예시에서는 해당 다이어그램에 제한되지 않고 단순하게 중재자 패턴의 핵심에 대한 예시를 보여주었습니다. 

 

강의에 예시는 호텔서비스를 보여줍니다.

호텔에서의 제공되는 특정한 공간들이 요구하는 클리닝 서비스를 호텔에서 제공하고, 게스트가 요구하는 것들을 각 공간이 제공하는 예시 입니다.

 

1. 먼저 "레스토랑" 과 "체육관" 클래스 입니다.

public class Restaurant {

    private CleaningService cleaningService = new CleaningService();

    public void dinner(Guest guest) {
        System.out.println("dinner " + guest);
    }

    public void clean() {
        cleaningService.clean(this);
    }
}

public class Gym {

    private CleaningService cleaningService;

    public void clean() {
        cleaningService.clean(this);
    }
}

 

2. "게스트" 클래스와 "호텔" 클래스입니다.

public class Guest {

    private Restaurant restaurant = new Restaurant();
    private CleaningService cleaningService = new CleaningService();

    public void dinner() {
        restaurant.dinner(this);
    }

    public void getTower(int numberOfTower) {
        cleaningService.getTower(this, numberOfTower);
    }
}

public class Hotel {

    public static void main(String[] args) {
        Guest guest = new Guest();
        guest.getTower(3);
        guest.dinner();

        Restaurant restaurant = new Restaurant();
        restaurant.clean();
    }
}

 

3. 다음은 게스트의 요청과, 호텔 공간들의 요청을 처리하는 클리닝 서비스 입니다.

  • 핵심은 여기 클래스입니다.
  • CleaningService  클래스가 Restaurant, Gym, Guest 클래스에 각각 직접적으로 참조하고 있습니다.
  • 이렇게 되면 양쪽의 클래스간의 의존도가 굉장히 높은 코드가 되어집니다. 
/**
 * 각 객체와 직접 연결되어있기 때문에 → 엄청난 의존성을 가지고 있는 클리닝 객체
 *
 *  이렇게 되면
 *  1. 테스트하기 어려움
 *  2. 코드의 유지보수도 힘들어짐
 *  3. 수정도 힘듬 (양쪽 다 수정해야하고 어디에 영향을 끼치는지 파악할 수 없음)
 */
public class CleaningService {

    public void clean(Restaurant restaurant) {
        System.out.println("Clean " + restaurant);
    }

    public void clean(Gym gym) {
        System.out.println("Clean " + gym);
    }

    public void getTower(Guest guest, int numberOfTower) {
        System.out.println(numberOfTower + " towers to " + guest);
    }
}

 

이걸 간단하게 하나의 클래스에만 의존성을 모두 몰아넣는게 중재자 패턴입니다.

각각 퍼져있는 의존성들을 차라리 중재자의 역할을 하는 별도의 클래스 1곳에서 관리하도록 하면 각각의 클래스들 끼리의 의존성은 존재하지 않기 때문에 조금 더 코드관리가 편해지는 장점을 가집니다.

/**
 * 모든 소통을 Mediator 객체를 통하기 때문에 의존성을 하나의 객체로만 몰아넣었음
 *
 */
public class FrontDeskMediator {

    private final CleaningService cleaningService = new CleaningService();
    private final Restaurant restaurant = new Restaurant();
    private final Gym gym = new Gym();
    
    public void getTowers(Guest guest, int numberOfTowers) {
        cleaningService.getTower(guest.getId(), numberOfTowers);
    }

    public String getRoomNumber(Integer guestId) {
        return guestId + "room number : 1";
    }

    public void dinner(Guest guest) {
        restaurant.dinner(guest.getId());
    }   
}

✔️ 중재자 패턴 장단점

장점

  • 컴포넌트 코드를 변경하지 않고 새로운 중재자를 만들어 사용할 수 있다.
  • 각각의 컴포넌트 코드를 보다 간결하게 유지할 수 있다.

단점

  • 중재자 역할을 하는 클래스의 복잡도와 결합도가 증가한다. (의존성을 한곳에 몰기때문에)

 

 

 

 

반응형