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

🧩 Template Method パターン

✅ 設計意図

  • 処理全体のテンプレート(流れ)を定義し、一部の処理をサブクラスに委ねる
  • ベタ書きされていた変化点のみを明示的に抽象化

✅ 適用理由

  • 通知の構成(送信先・本文など)の共通部分を明確にしつつ、差分だけを分けたい
  • 処理の流れが固定されているが、一部を柔軟に変えたいときに最適

✅ 向いているシーン

  • 処理手順が共通していて、特定ステップだけ異なるケース
  • 初期化・実行・終了などの「型」がある処理

✅ コード例

abstract class Notifier {
send(user: string, message: string) {
console.log(this.header());
console.log(this.formatMessage(message));
console.log(this.destination(user));
}

protected abstract header(): string;
protected abstract destination(user: string): string;
protected abstract formatMessage(message: string): string;
}

class EmailNotifier extends Notifier {
protected header(): string {
return "件名: お知らせ";
}

protected destination(user: string): string {
return `宛先: ${user}@example.com`;
}

protected formatMessage(message: string): string {
return `本文: ${message}`;
}
}

class SlackNotifier extends Notifier {
protected header(): string {
return "Slack 通知";
}

protected destination(user: string): string {
return `Slack宛: ${user}`;
}

protected formatMessage(message: string): string {
return `内容: ${message}`;
}
}

// 利用例
new EmailNotifier().send("hiroshi", "メールメッセージ");
new SlackNotifier().send("hiroshi", "Slackメッセージ");

✅ 解説

このコードは Template Method パターン を使用して、通知処理の共通フローを抽象クラス(Notifier)で定義し、 具体的な処理(メール通知や Slack 通知)をサブクラスで実装する設計を実現している。 Template Method パターンは、アルゴリズムの骨組みをスーパークラスで定義し、詳細な処理をサブクラスで実装するデザインパターン。

1. Template Method パターンの概要

  • AbstractClass: アルゴリズムの骨組みを定義し、具体的な処理をサブクラスに委譲する抽象クラス
    • このコードでは Notifier が該当
  • ConcreteClass: AbstractClass を継承し、抽象メソッドを実装して具体的な処理を提供するクラス
    • このコードでは EmailNotifierSlackNotifier が該当

2. 主なクラスとその役割

  • Notifier
    • 抽象クラス(AbstractClass
    • send メソッドで通知処理の共通フローを定義
    • ヘッダーを出力
    • メッセージをフォーマット
    • 宛先を出力
    • header, destination, formatMessage の抽象メソッドをサブクラスに委譲
  • EmailNotifier
    • Notifier を継承した具体クラス(ConcreteClass
    • メール通知のヘッダー、宛先、メッセージフォーマットを実装
  • SlackNotifier
    • Notifier を継承した具体クラス(ConcreteClass
    • Slack 通知のヘッダー、宛先、メッセージフォーマットを実装

3. UML クラス図

4. Template Method パターンの利点

  • コードの再利用: 共通の処理フローをスーパークラスにまとめることで、コードの重複を削減
  • 拡張性: 新しい通知方法を追加する場合も、Notifier を継承して抽象メソッドを実装するだけで対応可能
  • 一貫性: 共通の処理フローをスーパークラスで定義することで、処理の一貫性を確保

この設計は、共通の処理フローを持つが、一部の処理が異なる場合に非常に有効であり、コードの保守性と拡張性を向上させる。