Skip to main content

🧩 Template Method Pattern

✅ Intent

  • Define the skeleton of an algorithm in a base class and allow subclasses to override specific steps
  • Clarify where variation occurs, while ensuring the core logic remains consistent

✅ Motivation

  • You want to avoid duplicating the same processing flow in every notification type
  • Common logic (like logging, validation, structure) should be written once
  • Differences (such as formatting or destination) can be safely delegated to subclasses

✅ When to Use

  • The overall process is fixed, but some steps vary
  • You want to enforce a consistent flow and delegate differences
  • Ideal for message sending, form handling, lifecycle hooks, etc.

✅ Code Example

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メッセージ");

✅ Explanation

This example applies the Template Method pattern to encapsulate the common steps of sending a notification into an abstract class (Notifier), while allowing different implementations (like EmailNotifier and SlackNotifier) to define their own behavior for formatting and delivery.

1. Template Method Pattern Overview

  • AbstractClass: Defines the overall algorithm and declares abstract steps
    Notifier

  • ConcreteClass: Implements the specific steps defined in the abstract class
    EmailNotifier, SlackNotifier

2. Key Classes and Responsibilities

  • Notifier

    • The abstract base class
    • Defines the common send flow:
      • Generate header
      • Format message
      • Output destination
    • Delegates header(), destination(), and formatMessage() to subclasses
  • EmailNotifier

    • Implements email-specific header, destination, and message formatting
  • SlackNotifier

    • Implements Slack-specific behavior for the same steps

3. UML Class Diagram

4. Benefits of the Template Method Pattern

  • Consistency: All subclasses follow the same structure
  • DRY Principle: Common logic is centralized and not duplicated
  • Ease of Extension: New variants only need to implement a few methods
  • Separation of Concerns: Core flow is separated from customizable details

This pattern is highly effective when you have shared procedures across multiple variations, with only a few parts that change. It simplifies maintenance and ensures a consistent structure across all implementations.