Template Method Pattern¶
Category: Behavioral Pattern
Overview¶
Define the skeleton of an algorithm in a base class, allowing subclasses to override specific steps without changing the algorithm's structure. This pattern promotes code reuse and enforces a consistent algorithm structure across different implementations.
Usage Guidelines¶
Use when:
- Multiple classes share the same algorithm skeleton
- Some steps vary between implementations
- Want to enforce specific algorithm sequence
- Common steps should be implemented once
Avoid when:
- Each implementation is completely different
- Composition would be more flexible than inheritance
- No shared logic between implementations
- Algorithm structure changes frequently
Implementation¶
from __future__ import annotations
from abc import ABC, abstractmethod
class DataMiner(ABC):
"""Abstract class defining the template method for data mining."""
def mine(self, path: str) -> dict[str, str]:
"""Template method defining the data mining algorithm.
This method defines the skeleton of the algorithm. Subclasses
should not override this method.
Args:
path: Path to the data file.
Returns:
Dictionary containing mining results.
"""
data = self.open_file(path)
raw_data = self.extract_data(data)
analysis = self.analyze_data(raw_data)
self.close_file(data)
return analysis
@abstractmethod
def open_file(self, path: str) -> str:
"""Open the file."""
pass
@abstractmethod
def extract_data(self, data: str) -> str:
"""Extract data from the file."""
pass
def analyze_data(self, data: str) -> dict[str, str]:
"""Analyze the extracted data.
This is a hook method with a default implementation.
"""
return {"status": "analyzed", "data": data}
@abstractmethod
def close_file(self, data: str) -> None:
"""Close the file."""
pass
class PDFDataMiner(DataMiner):
"""Concrete data miner for PDF files."""
def open_file(self, path: str) -> str:
"""Open PDF file."""
return f"PDF({path})"
def extract_data(self, data: str) -> str:
"""Extract data from PDF."""
return f"Extracted from {data}"
def close_file(self, data: str) -> None:
"""Close PDF file."""
pass
class CSVDataMiner(DataMiner):
"""Concrete data miner for CSV files."""
def open_file(self, path: str) -> str:
"""Open CSV file."""
return f"CSV({path})"
def extract_data(self, data: str) -> str:
"""Extract data from CSV."""
return f"Parsed {data}"
def close_file(self, data: str) -> None:
"""Close CSV file."""
pass
Usage¶
# PDF data mining
pdf_miner = PDFDataMiner()
result = pdf_miner.mine("document.pdf")
print(result) # {'status': 'analyzed', 'data': 'Extracted from PDF(document.pdf)'}
# CSV data mining
csv_miner = CSVDataMiner()
result = csv_miner.mine("data.csv")
print(result) # {'status': 'analyzed', 'data': 'Parsed CSV(data.csv)'}
Trade-offs¶
Benefits:
- Common code is in one place promoting code reuse
- Algorithm structure is consistent across implementations
- Template method prevents algorithm modification
- Hook methods provide optional extension points
Drawbacks:
- Tight coupling through inheritance
- Subclass constraints may violate Liskov Substitution Principle
- Algorithm structure is fixed with limited flexibility
- Changes to template affect all subclasses
Real-World Examples¶
- Framework hooks like Django views, React lifecycle methods
- Data processing pipelines with ETL operations
- Testing frameworks with setUp, test, tearDown methods
- Build systems with pre-build, build, post-build steps
Related Patterns¶
- Strategy
- Factory Method
- Hook Method
API Reference¶
design_patterns.behavioral.template_method
¶
Template Method Pattern Module
The Template Method pattern defines the skeleton of an algorithm in a base class, allowing subclasses to override specific steps of the algorithm without changing its structure. This pattern promotes code reuse and enforces a consistent algorithm structure across different implementations.
Example
Data mining algorithms with different data formats:
Beverage
¶
Bases: ABC
Abstract class for making beverages using template method.
Source code in src/design_patterns/behavioral/template_method.py
add_condiments()
abstractmethod
¶
boil_water()
¶
brew()
abstractmethod
¶
pour_in_cup()
¶
prepare()
¶
Template method for preparing a beverage.
Returns:
| Type | Description |
|---|---|
list[str]
|
List of preparation steps. |
Source code in src/design_patterns/behavioral/template_method.py
wants_condiments()
¶
Hook method to determine if condiments should be added.
Returns:
| Type | Description |
|---|---|
bool
|
True if condiments should be added. |
BlackCoffee
¶
Bases: Beverage
Concrete beverage: Black coffee without condiments.
Source code in src/design_patterns/behavioral/template_method.py
CSVDataMiner
¶
Bases: DataMiner
Concrete data miner for CSV files.
Source code in src/design_patterns/behavioral/template_method.py
close_file(data)
¶
extract_data(data)
¶
Extract data from CSV.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
CSV file data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Extracted CSV data. |
open_file(path)
¶
Open CSV file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to CSV file. |
required |
Returns:
| Type | Description |
|---|---|
str
|
CSV file representation. |
send_report(analysis)
¶
Send CSV mining report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
analysis
|
dict[str, str]
|
Analysis results. |
required |
Coffee
¶
DataMiner
¶
Bases: ABC
Abstract class defining the template method for data mining.
Source code in src/design_patterns/behavioral/template_method.py
analyze_data(data)
¶
Analyze the extracted data.
This is a hook method with a default implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
Extracted data. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Analysis results. |
Source code in src/design_patterns/behavioral/template_method.py
close_file(data)
abstractmethod
¶
Close the file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
File data representation. |
required |
extract_data(data)
abstractmethod
¶
Extract data from the file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
File data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Extracted data. |
mine(path)
¶
Template method defining the data mining algorithm.
This method defines the skeleton of the algorithm. Subclasses should not override this method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the data file. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dictionary containing mining results. |
Source code in src/design_patterns/behavioral/template_method.py
open_file(path)
abstractmethod
¶
Open the file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the file. |
required |
Returns:
| Type | Description |
|---|---|
str
|
File data representation. |
send_report(analysis)
¶
Send the analysis report.
This is a hook method with a default implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
analysis
|
dict[str, str]
|
Analysis results. |
required |
PDFDataMiner
¶
Bases: DataMiner
Concrete data miner for PDF files.
Source code in src/design_patterns/behavioral/template_method.py
close_file(data)
¶
extract_data(data)
¶
Extract data from PDF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
PDF file data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Extracted PDF data. |
open_file(path)
¶
Open PDF file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to PDF file. |
required |
Returns:
| Type | Description |
|---|---|
str
|
PDF file representation. |
Tea
¶
XMLDataMiner
¶
Bases: DataMiner
Concrete data miner for XML files.
Source code in src/design_patterns/behavioral/template_method.py
analyze_data(data)
¶
Analyze XML data with custom logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
Extracted XML data. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Custom XML analysis. |
Source code in src/design_patterns/behavioral/template_method.py
close_file(data)
¶
extract_data(data)
¶
Extract data from XML.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
XML file data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Extracted XML data. |
open_file(path)
¶
Open XML file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to XML file. |
required |
Returns:
| Type | Description |
|---|---|
str
|
XML file representation. |