DPDesign Pattern Quest
#10 / 23
S構造DIFF

ファサード

Facade

ホテルのコンシェルジュ。中で誰がどう動いてるかは知らなくていい、頼むのは『窓口の1人』だけ。

Intent · 目的

複雑なサブシステム群への『簡単な窓口』を提供する。クライアントは中身の細かいクラスを知らずに、ファサード1つを呼べば目的を達成できるようになる。

Motivation · 動機

ホテルで「空港まで行きたい」と思った時。タクシー会社に電話して、配車時間を確認して、料金を確認して、行き先を伝えて……は面倒。コンシェルジュに『空港までお願いします』と言うだけで全部やってくれるのが理想。プログラムでも同じ。「メールを送る」のために SMTP接続→ヘッダ生成→MIMEエンコード→再送制御 を全部利用側に書かせるのは酷。`Mailer.send(to, body)` 1行で済む窓口を1個作れば、利用側はシンプルにでき、内部の実装も差し替えやすくなる。

適用場面

  • 1サブシステムの利用が複雑で、典型的な利用手順をまとめたい場合(メール送信、決済処理)。
  • 2クライアントとサブシステムの結合を緩めたい場合(後で内部を差し替えたい)。
  • 3サブシステムを段階的に置き換えていきたい場合 ── ファサードを境界線にする。

概念図

サンプルコード

class SmtpClient { connect(){} send(raw: string){ console.log("send:", raw); } }
class MimeEncoder { encode(body: string){ return `MIME(${body})`; } }
class HeaderBuilder { build(to: string){ return `To: ${to}\n`; } }

class Mailer {
  private smtp = new SmtpClient();
  private enc = new MimeEncoder();
  private hb = new HeaderBuilder();
  send(to: string, body: string){
    this.smtp.connect();
    const raw = this.hb.build(to) + this.enc.encode(body);
    this.smtp.send(raw);
  }
}

new Mailer().send("a@example.com", "Hello");
Pros · メリット
  • クライアントから見た複雑度を一気に下げられる。20個の API が1個の窓口に圧縮される。
  • サブシステムの結合を緩め、内部実装の差し替えがやりやすい。
  • ライブラリ作者にとっては『推奨ユースケース』を体系化する場所にもなる。
Cons · デメリット
  • 便利だからと何でも詰め込むと、ファサードが神クラス化する。『Mailer に支払い処理が…?』
  • 細粒度な制御をしたい場面ではファサード越しでは届かないことがある。
  • 下層が変わると、ファサードの API は据え置きでも内部修正の頻度は上がる。

関連パターン

⚔ ready to test

理解度を確かめる時間だ

3 問のクイズで、 このパターンを身体に染み込ませよう。

挑戦する →