ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 중재자 패턴 (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

Designed by Tistory.