Adapter

決済クライアントを変換して使う

インターフェースの違いを変換して合わせる

このデモで分かること: 呼び出し側は変えずに、既存の非互換なクラスを変換して使う

このデモで Adapter を使う理由

  • 支払い処理を呼ぶ側は pay(amount) だけ呼べればよいが、外部の決済クライアントは独自の単位(銭。1円=100銭の旧補助単位)と通貨コードを要求してくる。
  • 呼び出し側が外部クライアントの独自シグネチャに合わせて分岐すると、外部クライアントが増えるたびに呼び出し側が汚れる。
  • Adapter で外部クライアントを PaymentGateway に変換すれば、呼び出し側は差し替えを意識しなくてよい。

パターンなし vs このパターン(イメージ)

記事の本編ではなく、このデモ題材を if の山にした場合との対比です(疑似コード)。

パターンなし

// パターンなし(イメージ)
if (useLegacy) {
  // legacy は「銭」単位(1円=100銭)でしか受け取れない旧仕様なので変換が必要
  legacyClient.charge(amount.multiply(100).longValue(), "JPY");
} else {
  gateway.pay(amount);
}
// → 呼び出し側が外部クライアントの独自形式を知っている

Adapter あり

// Adapter
PaymentGateway gateway = new LegacyPaymentAdapter(legacyClient);
gateway.pay(amount);
// → 呼び出し側は PaymentGateway しか知らない

デモ

結果

MODERN-OK: 1000円を決済しました

呼び出し先の実装クラス

ModernPaymentGateway

呼び出し側は常に PaymentGateway インターフェースしか使いません。

操作 → 動いたクラス / メソッド

  1. 操作: 決済方式「モダン」で 1000 円を支払う
  2. → PaymentGateway.pay(1000)
  3. → ModernPaymentGateway.pay(...) … 変換なしでそのまま実装
  4. → 結果: MODERN-OK: 1000円を決済しました
記事は考え方・別サンプルの解説です。このページのデモ実装とはソースが異なります
(クラス名・題材はデモ用に簡略化しています)。