Pythonで実装するMediatorパターン：複雑な相互依存を一元的に調停する



## 概要

**Mediator（メディエーター）パターン**は、  
複数のオブジェクト間の複雑なやり取りを**“調停者”としての中央オブジェクトに一元化する設計パターン**である。

個々のコンポーネントが互いに直接参照し合うのではなく、Mediatorを介して通信することで、**オブジェクト同士の依存関係を緩和（疎結合）できる**。

---

## 1. なぜMediatorが必要か？

### ❌ 複数オブジェクトが相互に依存しすぎて、修正コストが爆発する

```python
class Button:
    def click(self):
        textbox.hide()
        dialog.open()

class TextBox:
    def input(self):
        button.disable()
```

→ **ロジックが絡み合い、変更に対する影響範囲が広がる**

---

### ✅ 各コンポーネントはMediatorに通知し、処理はMediatorに集約

```python
button.click()  → mediator.notify(sender, "click")
```

→ **イベントの流れが一元化され、個別の依存を解消**

---

## 2. 基本構造

### ✅ Mediatorインターフェース

```python
class Mediator:
    def notify(self, sender, event):
        raise NotImplementedError
```

---

### ✅ ConcreteMediator（具体的調停者）

```python
class DialogMediator(Mediator):
    def __init__(self):
        self.button = None
        self.textbox = None

    def notify(self, sender, event):
        if sender == self.button and event == "click":
            print("→ ボタンが押された。テキストボックスを隠す")
            self.textbox.hide()
        elif sender == self.textbox and event == "input":
            print("→ テキスト入力あり。ボタンを有効に")
            self.button.enable()
```

---

### ✅ 各コンポーネント

```python
class Button:
    def __init__(self, mediator: Mediator):
        self.mediator = mediator

    def click(self):
        print("[UI] ボタンがクリックされた")
        self.mediator.notify(self, "click")

    def enable(self):
        print("[UI] ボタンが有効になった")

class TextBox:
    def __init__(self, mediator: Mediator):
        self.mediator = mediator

    def input(self):
        print("[UI] テキスト入力された")
        self.mediator.notify(self, "input")

    def hide(self):
        print("[UI] テキストボックスを非表示にした")
```

---

### ✅ 使用例

```python
mediator = DialogMediator()
button = Button(mediator)
textbox = TextBox(mediator)

mediator.button = button
mediator.textbox = textbox

button.click()
textbox.input()
```

出力:
```
[UI] ボタンがクリックされた  
→ ボタンが押された。テキストボックスを隠す  
[UI] テキストボックスを非表示にした  
[UI] テキスト入力された  
→ テキスト入力あり。ボタンを有効に  
[UI] ボタンが有効になった
```

---

## 3. Python的応用：イベントベースの通知スタイル

```python
class EventMediator:
    def __init__(self):
        self.handlers = {}

    def register(self, event, handler):
        self.handlers.setdefault(event, []).append(handler)

    def notify(self, event, *args, **kwargs):
        for handler in self.handlers.get(event, []):
            handler(*args, **kwargs)
```

```python
mediator = EventMediator()
mediator.register("message_sent", lambda msg: print(f"ログ: {msg}"))
mediator.notify("message_sent", "Hello World")
```

→ **イベントディスパッチャとしての柔軟なMediator実装も可能**

---

## 4. 実務ユースケース

### ✅ UIフォーム内のコンポーネント連携制御

→ ボタン、入力欄、バリデーションの**状態制御をMediatorに集約**

---

### ✅ チャット・ゲーム内オブジェクト通信のハブ

→ 各プレイヤーやNPC間の通信を**中央ルータで調整**

---

### ✅ モジュール間の疎結合イベント伝達

→ ログ記録、バリデーション、通知など**クロスカット処理の一元化**

---

### ✅ マイクロサービス間通信のオーケストレーション

→ **複数サービスの連携を1つのハブで統括・調停**

---

## 5. よくある誤用と対策

### ❌ Mediatorがすべてのロジックを抱え込み、巨大化する

→ ✅ **責務を分割し、複数のMediatorに委任する**

---

### ❌ Mediatorが抽象化されず実装に依存しすぎる

→ ✅ **インターフェースやイベント名で疎結合に設計**

---

### ❌ 双方向依存が発生し、調停の意味がなくなる

→ ✅ **Mediatorからのみ通知・制御させ、依存方向を一方通行に**

---

## 結語

**Mediatorパターンとは、“複雑な関係性を一箇所に集約し、秩序ある調整を可能にする設計”である。**

- オブジェクト同士の直接依存を断ち、**拡張性とテスト性を高める**  
- イベント通知・状態変化・ロジック調整を**一元管理しやすくする**  
- Pythonでは動的ディスパッチや辞書ベースで、**柔軟に構築可能**

**Pythonicとは、“話す相手を限定せず、通訳を介して全体を制御すること”。  
Mediatorパターンはその会話の知性を、構造の調停者として明示する技法である。**