🧩 Template Method Pattern
✅ Intent
- Define the overall workflow (template) in a parent class, and allow subclasses to override specific steps
- Consolidate shared logic in the superclass
✅ Motivation
- Centralize common logic such as start/end logging
- Clearly expose "hook points" where behavior differs
✅ When to Use
- When the process flow is fixed but certain steps vary
- When you want to eliminate duplicated code across similar operations
✅ Code Example
- TypeScript
- PHP
- Python
abstract class Exporter {
export(data: string): void {
console.log("開始ログ");
this.doExport(data); // フックポイント(抽象メソッド)
console.log("完了ログ");
}
protected abstract doExport(data: string): void;
}
class PdfExporter extends Exporter {
protected doExport(data: string): void {
console.log(`PDF出力: ${data}`);
}
}
class CsvExporter extends Exporter {
protected doExport(data: string): void {
console.log(`CSV出力: ${data}`);
}
}
class XmlExporter extends Exporter {
protected doExport(data: string): void {
console.log(`XML出力: ${data}`);
}
}
// 利用例
const exporter = new CsvExporter();
exporter.export("データ123");
<?php
abstract class Exporter {
public function export(string $data): void {
echo "開始ログ\n";
$this->doExport($data); // フックメソッド(差分のみサブクラスに委譲)
echo "完了ログ\n";
}
abstract protected function doExport(string $data): void;
}
class PdfExporter extends Exporter {
protected function doExport(string $data): void {
echo "PDF出力: {$data}\n";
}
}
class CsvExporter extends Exporter {
protected function doExport(string $data): void {
echo "CSV出力: {$data}\n";
}
}
class XmlExporter extends Exporter {
protected function doExport(string $data): void {
echo "XML出力: {$data}\n";
}
}
// 利用例
$exporter = new XmlExporter();
$exporter->export("データ123");
from abc import ABC, abstractmethod
class Exporter(ABC):
def export(self, data: str):
print("開始ログ")
self.do_export(data) # フックメソッド
print("完了ログ")
@abstractmethod
def do_export(self, data: str):
pass
class PdfExporter(Exporter):
def do_export(self, data: str):
print(f"PDF出力: {data}")
class CsvExporter(Exporter):
def do_export(self, data: str):
print(f"CSV出力: {data}")
class XmlExporter(Exporter):
def do_export(self, data: str):
print(f"XML出力: {data}")
# 利用例
exporter = PdfExporter()
exporter.export("データ123")
✅ Explanation
This code applies the Template Method
pattern by defining a shared processing flow in an abstract class,
and delegating the variable parts to subclasses.
The Template Method
pattern defines the skeleton of an algorithm in a superclass, while deferring the detailed steps to subclasses.
1. Overview of the Template Method Pattern
-
AbstractClass: Defines the overall algorithm and delegates some steps to subclasses
- Represented by
Exporter
in this code
- Represented by
-
ConcreteClass: Implements the abstract methods to provide specific behavior
- Represented by
PdfExporter
,CsvExporter
, andXmlExporter
- Represented by
2. Key Classes and Their Roles
-
Exporter
- The abstract class (
AbstractClass
) - Defines the
export
method which:- Logs the start of the process
- Calls the abstract method
doExport
for custom export logic - Logs the completion of the process
- The
doExport
method must be implemented by subclasses
- The abstract class (
-
PdfExporter
,CsvExporter
,XmlExporter
- Concrete classes (
ConcreteClass
) - Implement
doExport
to export data in different formats (PDF, CSV, XML)
- Concrete classes (
3. UML Class Diagram
4. Benefits of the Template Method Pattern
- Code Reuse: Consolidates shared logic in the superclass, reducing duplication
- Extensibility: New behaviors can be added by simply implementing the abstract method in a new subclass
- Consistency: The overall flow is enforced by the superclass, ensuring uniform behavior
This design is highly effective when multiple processes share a common structure with minor differences.
It improves maintainability and extensibility by separating invariant logic from customizable steps.