-
중재자 패턴 (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
- 디스패처 서블릿은 다양한 핸들러와 어댑터들을 가지고 이들을 이어준다.
참고
'디자인 패턴' 카테고리의 다른 글
상태 패턴 (State Pattern) (0) 2022.08.13 메멘토 패턴 (Memento Pattern) (0) 2022.08.12 이터레이터 패턴 (Iterator Pattern) (0) 2022.08.04 인터프리터 패턴 (Interpreter Pattern) (0) 2022.08.03 커맨드 패턴 (Command Pattern) (0) 2022.08.02