#17 / 23
B振る舞いDIFF
メディエーター
Mediator
管制塔の発想だ。飛行機同士が直接喋ったらカオス。代わりに管制塔が全部の調整を引き受ける。
Intent · 目的
オブジェクト同士が互いを直接参照する代わりに、中央の『仲介役』を介してやり取りするようにする。N対Nの依存を1対Nに整理して、結合度を爆下げするパターン。
Motivation · 動機
ログイン画面を考えよう。ユーザー名入力欄が空になったらサインインボタンを無効化、パスワードに条件を満たさない文字が入ったらエラーラベルを赤くして、サインインボタンが押されたら入力をクリア…と、各部品が互いの状態を見て更新し合うようにすると、関係線がスパゲッティになる。Mediator なら、各部品は『何かが起きました』と中央に通報するだけ。誰がどう反応するかは仲介役のメソッド一覧を読めば全部わかる。グループLINEで全員が個別連絡し合うと混乱するけど、幹事がいれば話が早い、あの感じ。
適用場面
- 1互いに頻繁に通信しあう多数のオブジェクト(フォーム部品、ゲームのキャラクター同士)。
- 2オブジェクト間の相互参照が爆発しているUI / 状態同期。
- 3ある部品の変更が他の多数の部品に波及する複雑なロジック。
概念図
サンプルコード
interface DialogMediator { notify(sender: object, event: string): void; }
class TextField {
text = ""; m!: DialogMediator;
setText(t: string){ this.text = t; this.m.notify(this, "change"); }
}
class SubmitButton { enabled = false; }
class LoginDialog implements DialogMediator {
user = new TextField();
submit = new SubmitButton();
constructor(){ this.user.m = this; }
notify(sender: object, event: string){
if (sender === this.user && event === "change") {
this.submit.enabled = this.user.text.length > 0;
}
}
}
const d = new LoginDialog();
d.user.setText("alice");
console.log(d.submit.enabled); // truePros · メリット
- +部品同士の相互参照を消し、結合度がガクッと下がる。
- +新しい部品を追加するとき、他部品の存在を気にしなくていい。
- +全体の調整ロジックが仲介役1か所に集約され、見通しが良い。
Cons · デメリット
- −仲介役に責任が集中して『神オブジェクト』化しやすい。LoginDialog が全部署の業務を抱え込む役所みたいになる。
- −細かい UI まで適用すると過剰。発想の重さに見合う規模が必要。
- −仲介役の中身がブラックボックス化すると、その人がいないと改修できなくなる。
関連パターン
⚔ ready to test
理解度を確かめる時間だ
3 問のクイズで、 このパターンを身体に染み込ませよう。