디자인 패턴

중재자 패턴 (Mediator pattern)

개발정리 2022. 8. 11. 17:43

중재자 패턴


여러 객체들이 소통하는 방법을 캡슐화하는 패턴

  • 여러 컴포넌트간의 결합도를 중재자를 통해 낮출 수 있다.
  • 한 예로 비행기들은 관제탑이라는 Mediator 를 통해 서로 소통하는데, 이를 떠올리면서 학습하여 보자.

 

 

 

중재자 패턴 적용 전


 

호텔과 호텔의 여러 서비스들에 대한 코드이다. 

 

먼저 호텔을 살펴보자.

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

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

main 에서 guest (손님) 가 타월을 달라고 요청하고, 식사를 한다.

그리고 restaurant (식당) 에 청소를 요청한다.

 

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

  public void getTowel(Guest guest, int numberOfTowel) {
    System.out.println(numberOfTowel + " towels to " + guest);
  }

  public void clean(Restaurant restaurant) {
    System.out.println("clean " + restaurant);
  }
}
public class Guest {
  private Restaurant restaurant = new Restaurant();

  private CleaningService cleaningService = new CleaningService();

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

  public void getTowel(int numberOfTowel) {
    cleaningService.getTowel(this, numberOfTowel);
  }
}

Guest 는 restaurant 와 cleaningService 를 Aggregate(포함) 하고있다.

 

public class Gym {
  private CleaningService cleaningService;

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

Gym 은 cleaningService 를 Aggregate(포함) 하고있다.

 

public class Restaurant {
  private CleaningService cleaningService = new CleaningService();

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

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

Restaurant 은 cleaningService 를 Aggregate(포함) 하고있다.

 

 

문제점

  • 각 클래스를 보면 의존관계가 얽혀있는 것을 볼 수 있다. 
  • 이렇게 다양한 클래스들이 엮이게 되는 상황에서 중재자 패턴을 적용해보자.

 

 

Guest 클래스를 살펴보자. (Collegue A)

@Getter
@Setter
public class Guest {
  private int id;
  private FrontDesk frontDesk = new FrontDesk();

  public void getTowels(int numberOfTowels) {
    this.frontDesk.getTowels(this, numberOfTowels);
  }
  private void dinner(LocalDateTime dateTime) {
    this.frontDesk.dinner(this, dateTime);
  }
}

Guest 는  FrontDesk 를 가지고 있는데, Cleaning , Restaurant 등 모든 서비스를 FrontDesk(중재자) 를 통해 요청하고 있다.

 

 

FrontDesk (Mediator)

public class FrontDesk {
  private CleaningService cleaningService = new CleaningService();
  private Restaurant restaurant = new Restaurant();

  public void getTowels(Guest guest, int numberOfTowels) {
    cleaningService.getTowels(guest.getId(), numberOfTowels);
  }

  public String getRoomNumberFor(int guestId) {
    return guestId + "의 room number";
  }

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

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

FrontDesk 는 중재자로써 모든 서비스들을 알고 있어도 된다. Guest 가 요청한 서비스를 각 서비스들에게 전달한다.

 

 

CleaningService (Collegue B)

public class CleaningService {
  private FrontDesk frontDesk = new FrontDesk();

  public void getTowels(int guestId, int numberOfTowels) {
    String roomNumber = this.frontDesk.getRoomNumberFor(guestId);
    System.out.println(roomNumber + "에 " + numberOfTowels + " 개의 towels 들을 배달했습니다.");
  }

  public void clean() {
    System.out.println("청소하기");
  }
}

 

 

Restaurant (CollegueC)

public class Restaurant {
  private FrontDesk frontDesk = new FrontDesk();

  public void cleanRestaurant() {
    frontDesk.clean();
  }

  public void dinner(int id, LocalDateTime dateTime) {
    System.out.println(id + "번 Guest 의 저녁식사를 " + dateTime + " 에 준비해두겠습니다.");
  }
}

Restaurant 역시 clean 서비스가 필요하다면 직접 CleanService 에게 요청하는것이 아니라 FrontDesk 를 통해 요청하고 있다.

 

 

 

장점과 단점


장점

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

 

단점

  • 중재자 역할을 하는 클래스의 복잡도화 결합도가 증가한다.
  • 의존성이 한 곳으로 몰린다.

 

 

 

실무에선 어떻게 쓰이나?


자바

  • ExcutorService
  • Executor

 

스프링

  • MVC 의 DispatcherService
    • 디스패처 서블릿은 다양한 핸들러와 어댑터들을 가지고 이들을 이어준다.

 

 

 

참고


 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com