중재자(Mediator) 패턴
디자인 패턴 ·중재자 패턴은 복잡한 객체 간의 상호 작용을 단순화하기 위해 중재자 객체를 도입하는 디자인 패턴입니다. 중재자 객체는 다른 객체 간의 통신을 캡슐화하고 객체 간의 의존성을 줄이는 데 도움이 됩니다.
구성 요소
- 중재자(Mediator): 다른 객체 간의 통신을 캡슐화하는 객체의 인터페이스입니다.
- 동료(Colleague): 중재자와 통신하는 객체의 인터페이스입니다
구현:
- 인터페이스 생성: 중재자 역할을 수행할 인터페이스를 정의합니다.
- 중재자 구현: 인터페이스를 구현하는 중재자 클래스를 생성합니다. 중재자는 여러 개의 동료 객체들과 통신하며, 필요한 작업을 수행합니다.
- 동료 객체 구현: 중재자와 연결할 여러 개의 동료 객체를 생성합니다.
- 동료 객체와 중재자 연결: 동료 객체들은 중재자의 인스턴스를 참조하여 연결합니다.
장점
- 유연성: 중재자 패턴은 관련된 객체 사이의 상호 작용을 단순화하고 유연하게 만든다. 중재자 객체는 관련된 객체들이 상호작용할 수 있도록 연결하고 관리하기 때문에 다른 객체를 추가하거나 삭제할 때도 유연하게 대처할 수 있다.
- 유지보수성: 중재자 패턴은 시스템을 구조화하여 유지보수하기 쉽게 만든다. 관련된 객체들의 상호작용을 중재자에게 위임하므로 코드 구조가 단순해지고 수정이 쉬워진다.
- 결합도 감소: 중재자 패턴은 객체들 간의 결합도를 감소시킨다. 관련된 객체들끼리 직접 의사소통하지 않고 중재자를 통해서 상호작용하기 때문에 객체간의 의존성이 줄어들고 유연성이 증가한다.
단점
- 복잡성: 중재자 패턴은 중재자 객체가 추가되어야 하기 때문에 프로그램의 복잡도가 증가할 수 있다. 또한 중재자의 책임이 많아지면서 중재자 객체 자체가 복잡해질 수 있다.
- 성능 문제: 중재자 패턴은 메시지 전달 과정에서 오버헤드가 발생할 수 있기 때문에 대규모 시스템에서는 성능 문제가 발생할 수 있다.
- 너무 많은 역할을 담당: 중재자가 너무 많은 역할을 담당하는 상황이 발생할 수 있다. 이 경우 중재자의 기능을 분리하기 위해 추가적인 클래스가 필요해지며, 구조가 복잡해질 수 있다. 또한 중재자가 다른 객체들 간의 모든 상호작용을 중재하기 때문에 적절한 역할 분담이 이루어지지 않으면 중재자의 부담이 커지고 역할 충돌이 발생할 수 있다.
예시
손님은 레스토랑에 예약을 하거나, 청소업체에 룸 청소를 부탁하거나, 타월을 요청할때 프론트데스크만 알고 있으면된다.
Mediator
public class FrontDesk {
private final CleaningService cleaningService;
private final Gym gym;
private final Restaurant restaurant;
public FrontDesk(CleaningService cleaningService, Gym gym, Restaurant restaurant) {
this.cleaningService = cleaningService;
this.gym = gym;
this.restaurant = restaurant;
}
public void getTower(int roomNumber, int numberOfTower) {
this.cleaningService.getTower(roomNumber, numberOfTower);
}
public void cleanGym() {
this.cleaningService.clean(this.gym);
}
public void cleanRestaurant(){
this.cleaningService.clean(this.restaurant);
}
public void dinner(int roomNumber, LocalDateTime time) {
this.restaurant.dinner(roomNumber, time);
}
public int getRoomNumber(){
return 1111;
}
}
Colleague
public class CleaningService {
public void clean(Gym gym) {
System.out.println("clean " + gym);
}
public void getTower(int roomNumber, int numberOfTower) {
System.out.println(numberOfTower + " towers to " + roomNumber);
}
public void clean(Restaurant restaurant) {
System.out.println("clean " + restaurant);
}
}
public class Restaurant {
public void dinner(int roomNumber, LocalDateTime time) {
System.out.println("dinner " + roomNumber + " at " + time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm")));
}
}
public class Gym {
private FrontDesk frontDesk;
}
Client
public class Guest {
private int roomNumber;
private final FrontDesk frontDesk;
public Guest(FrontDesk frontDesk) {
this.frontDesk = frontDesk;
}
public void dinner(LocalDateTime time) {
frontDesk.dinner(this.roomNumber, time);
}
public void getTower(int numberOfTower) {
frontDesk.getTower(this.roomNumber, numberOfTower);
}
public void setRoomNumber(int roomNumber) {
this.roomNumber = roomNumber;
}
}
class HotelTest {
@Test
public void guest_test() {
FrontDesk frontDesk = new FrontDesk(new CleaningService(), new Gym(), new Restaurant());
Guest guest = new Guest(frontDesk);
guest.setRoomNumber(frontDesk.getRoomNumber());
guest.getTower(3);
guest.dinner(LocalDateTime.now());
frontDesk.cleanGym();
frontDesk.cleanRestaurant();
}
}
결론
중재자 패턴은 복잡한 시스템에서 객체간 상호작용을 조율하는 유용한 디자인 패턴입니다. 이 패턴을 사용하면 객체간 결합도를 줄이고 유연성과 확장성을 향상시킬 수 있습니다. 단, 너무 많은 역할을 부여하면 중재자에게 의존성이 과도하게 집중되어 오버헤드가 발생해 성능문제가 생길 수 있다.
예제는 이곳 에서 확인하실수 있습니다.