メインコンテンツまでスキップ

🧩 Bridge × Strategy

✅ 組み合わせの意図

  • Bridge パターンによって「通知手段(メール / Slack など)」と「通知内容の表現(プレーン / HTML)」という独立した 2 軸を分離
  • Strategy パターンで通知内容の組み立て方を外部化し、通知方式 × 表現方法の柔軟な組み合わせを可能にする

共通の通知処理を Notifier でまとめつつ、出力方式(メール / Slack)とメッセージの構成ロジック(プレーン / HTML)を柔軟に組み合わせられる設計を実現。

✅ よく使われるシーン

  • 通知の表現方式(テキスト / HTML / Markdown)と送信方式(メール / Slack など)を自由に組み合わせたいとき
  • 拡張の軸が複数あるが、それぞれを独立して設計・拡張したいとき
  • UI とテーマデータと表示手段など、独立した 2 軸を持つ構成で再利用性を高めたいとき

✅ UML クラス図

✅ コード例

interface PaymentStrategy {
pay(amount: number): void;
}

class CreditCardPayment implements PaymentStrategy {
pay(amount: number): void {
console.log(`[CreditCard] Paid ${amount}`);
}
}

class PayPalPayment implements PaymentStrategy {
pay(amount: number): void {
console.log(`[PayPal] Paid ${amount}`);
}
}

interface PaymentState {
handle(amount: number): void;
setStrategy(strategy: PaymentStrategy): void;
}

class ReadyState implements PaymentState {
constructor(private strategy: PaymentStrategy) {}

handle(amount: number): void {
console.log("Ready to process payment");
this.strategy.pay(amount);
}

setStrategy(strategy: PaymentStrategy): void {
this.strategy = strategy;
}
}

class DisabledState implements PaymentState {
handle(amount: number): void {
console.log("Payment is currently disabled");
}

setStrategy(strategy: PaymentStrategy): void {
console.log("Cannot set strategy while disabled");
}
}

class PaymentContext {
constructor(private state: PaymentState) {}

setState(state: PaymentState) {
this.state = state;
}

setStrategy(strategy: PaymentStrategy) {
this.state.setStrategy(strategy);
}

pay(amount: number) {
this.state.handle(amount);
}
}

// Usage
const context = new PaymentContext(new ReadyState(new CreditCardPayment()));
context.pay(100);

context.setStrategy(new PayPalPayment());
context.pay(200);

context.setState(new DisabledState());
context.pay(300);

✅ 解説

  • Notifier は、通知手段の抽象クラス。内部に MessageStrategy を持ち、メッセージの組み立て方を外部化Strategy)。
  • EmailNotifier, SlackNotifier はそれぞれ異なる通知チャネルを提供(Bridge の実装側)。
  • MessageStrategy はメッセージのフォーマット戦略で、PlainMessageStrategyHtmlMessageStrategy によって差し替え可能。
  • 通知方式とメッセージ構成方式が独立して変更・拡張できる構造になっている。

✅ まとめ

  • Bridge により「通知方式の拡張」と「通知メッセージ構成」の関心を分離
  • Strategy によりメッセージ内容の構築方法を切り替え可能
  • 拡張の自由度が高く、「どの通知方式 × どの表現方式」という柔軟な組み合わせを可能にする

この構造は、多軸での拡張が求められる実務において非常に効果的で、設計の保守性・再利用性を大きく向上させる。