🧩 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
- TypeScript
- PHP
- Python
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メッセージ");
<?php
abstract class Notifier {
public function send(string $user, string $message): void {
echo $this->header() . "\n";
echo $this->formatMessage($message) . "\n";
echo $this->destination($user) . "\n";
}
abstract protected function header(): string;
abstract protected function destination(string $user): string;
abstract protected function formatMessage(string $message): string;
}
class EmailNotifier extends Notifier {
protected function header(): string {
return "件名: お知らせ";
}
protected function destination(string $user): string {
return "宛先: {$user}@example.com";
}
protected function formatMessage(string $message): string {
return "本文: {$message}";
}
}
class SlackNotifier extends Notifier {
protected function header(): string {
return "Slack 通知";
}
protected function destination(string $user): string {
return "Slack宛: {$user}";
}
protected function formatMessage(string $message): string {
return "内容: {$message}";
}
}
// 利用例
(new EmailNotifier())->send("hiroshi", "メールメッセージ");
(new SlackNotifier())->send("hiroshi", "Slackメッセージ");
from abc import ABC, abstractmethod
class Notifier(ABC):
def send(self, user: str, message: str):
print(self.header())
print(self.format_message(message))
print(self.destination(user))
@abstractmethod
def header(self) -> str: pass
@abstractmethod
def destination(self, user: str) -> str: pass
@abstractmethod
def format_message(self, message: str) -> str: pass
class EmailNotifier(Notifier):
def header(self) -> str:
return "件名: お知らせ"
def destination(self, user: str) -> str:
return f"宛先: {user}@example.com"
def format_message(self, message: str) -> str:
return f"本文: {message}"
class SlackNotifier(Notifier):
def header(self) -> str:
return "Slack 通知"
def destination(self, user: str) -> str:
return f"Slack宛: {user}"
def format_message(self, message: str) -> str:
return f"内容: {message}"
# 利用例
EmailNotifier().send("hiroshi", "メールメッセージ")
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()
, andformatMessage()
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.