On this page
Template Method
The Template Method pattern defines the skeleton of an algorithm in a base class, letting subclasses override specific steps without changing the algorithm structure.
Problem
Multiple classes share the same algorithm structure but differ in specific steps.
Solution
abstract class DataMiner {
// Template method — defines the algorithm skeleton
public final void mine(String path) {
openFile(path);
extractData();
analyzeData();
closeFile();
}
protected abstract void openFile(String path);
protected abstract void extractData();
protected void analyzeData() { // hook — optional override
System.out.println("Default analysis");
}
protected abstract void closeFile();
}
class PDFMiner extends DataMiner {
protected void openFile(String path) { System.out.println("Opening PDF: " + path); }
protected void extractData() { System.out.println("Extracting PDF text"); }
protected void closeFile() { System.out.println("Closing PDF"); }
}
class CSVMiner extends DataMiner {
protected void openFile(String path) { System.out.println("Opening CSV: " + path); }
protected void extractData() { System.out.println("Parsing CSV rows"); }
protected void analyzeData() { System.out.println("CSV statistical analysis"); }
protected void closeFile() { System.out.println("Closing CSV"); }
}
Template Method Structure
| Element | Description |
|---|---|
| Template method | final method defining algorithm skeleton |
| Abstract methods | Must be overridden by subclasses |
| Hook methods | Optional override with default behavior |
| Concrete methods | Shared implementation in base class |
Java Examples
// AbstractList provides template for get/set/size
abstract class AbstractList<E> {
public boolean add(E e) { add(size(), e); return true; } // template
abstract public E get(int index); // primitive
abstract public int size(); // primitive
}
// HttpServlet service method
protected void service(HttpServletRequest req, HttpServletResponse resp) {
if (req.getMethod().equals("GET")) doGet(req, resp);
else if (req.getMethod().equals("POST")) doPost(req, resp);
// ...
}
// JUnit test lifecycle — @BeforeEach, @Test, @AfterEach
Hook Methods
Optional steps subclasses can override:
abstract class Game {
public final void play() {
initialize();
if (shouldShowIntro()) { // hook
showIntro();
}
runGameLoop();
cleanup();
}
protected boolean shouldShowIntro() { return true; } // default: show intro
protected void showIntro() { System.out.println("Welcome!"); }
protected abstract void runGameLoop();
}
Template Method vs Strategy
| Template Method | Strategy |
|---|---|
| Inheritance-based | Composition-based |
| Fixed algorithm skeleton | Entire algorithm swappable |
| Compile-time binding | Runtime binding |
| “Is-a” relationship | “Has-a” relationship |
When to Use
- Subclasses share a common algorithm with varying steps
- You want to control which steps are overridden (use
finaltemplate method) - Code reuse through inheritance is acceptable
Best Practices
- Mark the template method as
finalto prevent altering the algorithm structure - Provide hook methods instead of abstract methods when override is optional
- Prefer composition (Strategy) when runtime flexibility is needed
- Keep the number of abstract methods small — too many reduces usefulness