DP-17: Mediator パターン
複数のオブジェクト間の複雑な相互通信を、調停者(Mediator)オブジェクトに集約するパターンです。 各オブジェクトは互いを直接参照せず、Mediator を通じて通信することで、 依存関係を整理して保守性を高めます。
Mediator パターンとは
チャットアプリで5人のユーザーがいる場合、全員が互いを直接参照すると最大10本の依存関係が生まれます。 ユーザーが増えるにつれて依存関係は爆発的に増加し、コードが複雑になります。 Mediator パターンはこの問題を解決します。各ユーザーはチャットルーム(Mediator)だけを知り、 メッセージの配信はすべて Mediator が担います。これにより依存関係が「各ユーザー→Mediator」の形に整理されます。
Mediator パターンの登場人物
- Mediator(調停者): 通信ロジックを一元管理するインターフェース(例: ChatMediator)
- ConcreteMediator(具体調停者): 実際の通信処理を実装する(例: ChatRoom)
- Colleague(同僚): Mediator を通じて通信する各コンポーネント(例: ChatUser)
GUI フレームワークでは、フォームの各入力コンポーネント(テキストボックス・ボタン・チェックボックスなど)が 互いの状態に応じて活性/非活性を切り替える処理を Mediator で管理するのが典型的な使用例です。
サンプルコード
Java 8 では Mediator インターフェースと抽象クラスを組み合わせて実装します。各ユーザーは ChatRoom(Mediator)を介してのみ通信し、互いを直接参照しません。
よくあるミス・注意点
⚠️ Mediator に処理を集めすぎて「神クラス」になる
Mediator パターンは依存関係を整理しますが、通信ロジックを詰め込みすぎると Mediator 自体が肥大化して保守しにくくなります。 Mediator は「誰に転送するか」だけを担い、ビジネスロジックは各 Colleague クラスに残しましょう。
⚠️ Colleague が Mediator をバイパスして直接通信する
Colleague 同士が this の参照を渡し合って 直接メソッドを呼ぶと、Mediator パターンの意味が失われます。 Colleague は必ず Mediator 経由で通信するルールを徹底しましょう。
⚠️ Observer パターンとの混同
Observer パターンは「1対多の通知」を目的とし、通知元はどのオブジェクトが購読しているか意識しません。 Mediator パターンは「多対多の相互通信を仲介」することを目的とし、Mediator が通信の全体像を把握します。 目的が異なるため、用途に応じて選択しましょう。
テストする観点
- メッセージを送信したとき、送信者自身には届かず、他の全ユーザーに届くこと
- 管理者が送信したとき、メッセージに「[管理者通知]」プレフィックスが付くこと
- ユーザーを1人だけ登録した状態でメッセージを送っても、エラーが起きないこと(境界値)
- ユーザーが0人のとき、メッセージを送っても何も起きないこと(境界値)
- 同じユーザーを2回追加したとき、メッセージが2回届かないこと(重複登録の確認)
- Colleague が Mediator のみを知り、他の Colleague インスタンスを直接保持していないこと