자바 디자인 패턴 용어 사전
행위 패턴중재자

Mediator

객체 간 직접 참조를 없애고 중재자를 통해 소통하게 하는 패턴. N:N을 1:N으로 바꾼다.

객체들이 서로 직접 참조하지 않고 중재자를 통해 소통하게 하는 패턴.

무엇을 푸는가 — N:N 결합

Before   버튼 ↔ 체크박스 ↔ 입력창 ↔ 목록  (서로를 다 안다)
         객체 n 개면 관계가 최대 n(n-1)/2

After    버튼 → 중재자 ← 체크박스
              ↑     ↑
           입력창   목록          각자는 중재자만 안다 → 관계 n 개
interface Mediator { void notify(Component sender, String event); }

class DialogMediator implements Mediator {
    private CheckBox agree; private Button submit;
    public void notify(Component sender, String event) {
        if (sender == agree && event.equals("change"))
            submit.setEnabled(agree.isChecked());   // 상호작용 규칙이 여기 모인다
    }
}

Observer와의 차이

  • Observer — 발행자 → 구독자 단방향 통지. 발행자는 구독자를 모른다

    • '상태가 바뀌었다' 를 알린다
  • Mediator — 양방향 조율. 중재자가 참여자 모두를 안다

    • '누가 무엇을 하면 누가 어떻게 반응한다' 는 규칙을 담는다
  • 실무에서는 Mediator 를 Observer 로 구현하는 경우도 많다 (이벤트 버스)

대가 — 중재자가 God Object가 된다

모든 상호작용 규칙이 한 곳에 모이므로 참여자가 늘수록 중재자가 비대해진다

  • 화면·기능 단위로 중재자를 나눈다
  • 규칙이 단순하면 그냥 직접 참조가 낫다

실무에서

java.util.Timer                       // 태스크 실행 조율
ExecutorService                       // 작업 ↔ 스레드 중재
Spring ApplicationEventPublisher      // 이벤트 버스형
MVC 의 Controller                     // 모델 ↔ 뷰 중재

면접 함정

  • "Observer의 다른 이름" → 단방향 통지 vs 양방향 조율로 다르다.
  • 무조건 도입 → 참여자가 적으면 중재자가 불필요한 간접층이 된다.

이벤트 버스로 구현하는 형태

@Component
class OrderService {
    private final ApplicationEventPublisher publisher;
    void place(Order o) { publisher.publishEvent(new OrderPlaced(o.getId())); }
}

@Component
class NotificationHandler {
    @EventListener void on(OrderPlaced e) { ... }
}
  • 장점 — 결합이 끊긴다 — 구독자를 추가해도 발행자를 안 고친다
  • 대가 — 흐름이 코드에서 안 보인다 ("이 이벤트를 누가 받나" 를 찾기 어렵다)
    • 트랜잭션 경계가 헷갈린다 (@TransactionalEventListener 필요)

언제 과설계인가

  • 참여자가 2~3개다 → 직접 참조가 더 읽기 쉽다
  • 상호작용 규칙이 단순하다 → 중재자가 빈 껍데기가 된다
  • 흐름 추적이 중요한 도메인(결제·정산) → 간접층이 디버깅을 방해한다

비대화를 막는 법

화면·유스케이스 단위로 중재자를 나누고, 중재자는 조율만 하고 판단은 참여자가 하게 한다. 규칙이 늘면 규칙 객체로 다시 추출한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 행위 패턴 ② — 돌고, 알리고, 되돌린다