Use when multiple classes share the same algorithm skeleton but differ in specific steps — defining the invariant structure once in a base class and letting subclasses override only the varying parts.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add jeffreytse/grimoire-core --skill apply-template-method-pattern --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Apply Template Method Pattern?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeffreytse-apply-template-method-pattern)More formats (shields.io, HTML) on the badges page.
---
name: apply-template-method-pattern
description: Use when multiple classes share the same algorithm skeleton but differ in specific steps — defining the invariant structure once in a base class and letting subclasses override only the varying parts.
source: "Gamma, Helm, Johnson, Vlissides, \"Design Patterns: Elements of Reusable Object-Oriented Software\" (1994) pp. 325–330; Java AbstractList (size() and get() are abstract); Django class-based views; JUnit lifecycle hooks (setUp/tearDown)"
tags: [design-patterns, behavioral, template-method, oop, developer, code-reuse, algorithm-skeleton]
related: [apply-strategy-pattern, apply-inheritance-correctly, apply-solid-principles]
---
# Apply Template Method Pattern
Define the skeleton of an algorithm in a base class, deferring specific steps to subclasses — so subclasses can redefine parts of the algorithm without changing its overall structure.
## Why This Is Best Practice
**Adopted by:** Java's `AbstractList` (implements the full `List` contract based on
just `size()` and `get()` — subclasses provide those two methods, inheriting 30+ free
implementations), Django's class-based views (`View.dispatch()` is the template method
— subclasses override `get()`, `post()`, etc.), JUnit's test lifecycle
(`setUp()`/`tearDown()` are hook methods in the template), and Java's `HttpServlet`
(`service()` dispatches to overridable `doGet()`/`doPost()`).
**Impact:** GoF documents that Template Method is one of the most fundamental techniques
for code reuse via inheritance. Django's class-based views reduce view code by 60–80%
for standard CRUD operations — because the template (`dispatch`, `render`) is in the
base class and only the business logic step changes.
**Why best:** Code duplication — the alternative — copies the algorithm skeleton into
every subclass. A bug or enhancement to the skeleton requires editing every copy.
Template Method edits once; all subclasses inherit the fix.
Sources: Gamma et al. (1994) pp. 325–330; Django class-based views documentation;
Java `AbstractList` source
## Steps
### Step 1: Identify the algorithm skeleton and the varying steps
```
Skeleton (invariant): read data → process → format output → write result
Varying steps: how to read, how to process, how to format
```
### Step 2: Implement the template method in the base class — call abstract steps
```python
from abc import ABC, abstractmethod
class ReportGenerator(ABC):
def generate(self, data_source: str) -> str:
"""Template method — defines the algorithm skeleton."""
raw_data = self._read_data(data_source)
processed = self._process(raw_data)
formatted = self._format(processed)
self._write(formatted)
return formatted
@abstractmethod
def _read_data(self, source: str) -> list: ...
@abstractmethod
def _process(self, data: list) -> dict: ...
@abstractmethod
def _format(self, data: dict) -> str: ...
def _write(self, output: str) -> None:
"""Hook — optional override. Default: print."""
print(output)
```
### Step 3: Implement concrete subclasses — override only the varying steps
```python
class CSVReportGenerator(ReportGenerator):
def _read_data(self, source: str) -> list:
import csv
with open(source) as f:
return list(csv.reader(f))
def _process(self, data: list) -> dict:
return {"rows": len(data), "cols": len(data[0]) if data else 0}
def _format(self, data: dict) -> str:
return f"CSV Report: {data['rows']} rows × {data['cols']} columns"
class JSONReportGenerator(ReportGenerator):
def _read_data(self, source: str) -> list:
import json
with open(source) as f:
return json.load(f)
def _process(self, data: list) -> dict:
return {"count": len(data)}
def _format(self, data: dict) -> str:
return f"JSON Report: {data['count']} records"
```
### Step 4: Distinguish abstract steps from hooks
- **Abstract steps** (marked `@abstractmethod`): must be overridden — they have no default
- **Hooks** (concrete but empty or no-op): optionally overridden — they extend behavior without replacing it
```python
def _write(self, output: str) -> None:
print(output) # hook — override to write to file, send email, etc.
```
### Step 5: Mark the template method as final (or document it as non-overridable)
The template method defines the algorithm contract. Subclasses should override only the steps, not the skeleton.
```python
def generate(self, data_source: str) -> str:
# Python has no `final` keyword — document explicitly
# Subclasses: override _read_data, _process, _format, _write only
...
```
## When NOT to Use
- **When subclasses override the template method itself** — this defeats the pattern. If subclasses need full algorithm control, `apply-strategy-pattern` is correct (composition over inheritance).
- **Deep inheritance hierarchies** — Template Method encourages subclassing. If the hierarchy grows beyond 2–3 levels, composition becomes harder to navigate. Prefer Strategy at that point.
- **When "varying steps" are independent of each other** — if steps A and B vary independently, Strategy with two injected behaviors is more flexible than a subclass hierarchy.
## Common Mistakes
**Subclass overriding the template method.** If `CSVReportGenerator.generate()` overrides `ReportGenerator.generate()`, the skeleton is broken. The template method is the invariant; override only the abstract steps.
**Too many abstract steps.** If every step is abstract, there's no shared skeleton — subclasses duplicate the orchestration. Keep the skeleton meaningful (3–6 steps); if one step always needs overriding alone, consider a Strategy for that step.
**Confusing Template Method with Strategy.** Template Method uses inheritance — subclass IS-A base. Strategy uses composition — context HAS-A strategy. If the "algorithm" varies per instance at runtime, use Strategy. If it varies per class, use Template Method.Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!