Template Method Pattern
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 73 of 87.
The Template Method Pattern is a behavioral design pattern that defines the skeleton of an algorithm in a base class, allowing subclasses to override specific steps without changing the overall structure. Think of it like a recipe: the general cooking process stays the same, but individual ingredients or techniques can vary.
The pattern uses an abstract class with a template method that calls a sequence of steps. Some steps have default implementations, while others are abstract and must be implemented by subclasses:
abstract class DataProcessor {
// Template method - defines the algorithm structure
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Default implementation (hook method)
void saveData() {
System.out.println("Saving to default location");
}
}
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}
class XMLProcessor extends DataProcessor {
void readData() {
System.out.println("Reading XML file");
}
void processData() {
System.out.println("Parsing XML data");
}
}The template method is typically marked final to prevent subclasses from altering the algorithm's structure. When called, it executes the same sequence for all subclasses:
DataProcessor csv = new CSVProcessor();
csv.process();
// Output:
// Reading CSV file
// Parsing CSV data
// Saving to default locationThe Template Method Pattern is ideal when you have algorithms that share the same structure but differ in specific steps. It promotes code reuse by placing common logic in the base class while allowing customization through inheritance.
Challenge
EasyLet's build a document generation system using the Template Method Pattern! You'll create a framework where different document types (reports and invoices) follow the same generation process but customize specific steps. This is perfect for scenarios where the overall workflow is fixed, but the details vary by document type.
You'll organize your code across four files:
DocumentGenerator.java: Create the abstract base class that defines the template method. YourDocumentGeneratorshould have:A
finalmethod calledgenerateDocument()that defines the algorithm skeleton by calling three steps in order:createHeader(),createBody(), andcreateFooter().Two abstract methods:
createHeader()andcreateBody()that subclasses must implement.A hook method
createFooter()with a default implementation that prints--- End of Document ---.ReportGenerator.java: Create a concrete subclass for generating reports. It should take a report title (String) through its constructor.The
createHeader()method prints=== REPORT: [title] ===The
createBody()method printsReport content goes here...Use the inherited default footer.
InvoiceGenerator.java: Create another concrete subclass for generating invoices. It should take a customer name (String) and an amount (double) through its constructor.The
createHeader()method prints*** INVOICE ***The
createBody()method printsCustomer: [name]on one line, thenAmount Due: $[amount]on the next line (format amount to two decimal places).Override
createFooter()to printThank you for your business!Main.java: Bring your template method system together! You'll receive three inputs: a report title (String), a customer name (String), and an invoice amount (double).Create a
ReportGeneratorwith the title and callgenerateDocument(). Print an empty line for separation. Then create anInvoiceGeneratorwith the customer name and amount, and callgenerateDocument().
You will receive three inputs in order: report title (String), customer name (String), and invoice amount (double).
For example, with inputs Q4 Sales, Acme Corp, and 1500.00, your output would be:
=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---
*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!Notice how both document types follow the same three-step process defined in the template method, but each customizes the steps differently. The ReportGenerator uses the default footer while InvoiceGenerator provides its own—this is the power of hook methods in the Template Method Pattern!
Cheat sheet
The Template Method Pattern is a behavioral design pattern that defines the skeleton of an algorithm in a base class, allowing subclasses to override specific steps without changing the overall structure.
The pattern uses an abstract class with a template method that calls a sequence of steps. Some steps have default implementations, while others are abstract and must be implemented by subclasses:
abstract class DataProcessor {
// Template method - defines the algorithm structure
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Default implementation (hook method)
void saveData() {
System.out.println("Saving to default location");
}
}Concrete subclasses implement the abstract methods:
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}The template method is marked final to prevent subclasses from altering the algorithm's structure. When called, it executes the same sequence for all subclasses:
DataProcessor csv = new CSVProcessor();
csv.process();
// Output:
// Reading CSV file
// Parsing CSV data
// Saving to default locationKey characteristics:
- Template method is
finaland defines the algorithm structure - Abstract methods must be implemented by subclasses
- Hook methods provide default implementations that can be optionally overridden
- Promotes code reuse by placing common logic in the base class
Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String reportTitle = scanner.nextLine();
String customerName = scanner.nextLine();
double invoiceAmount = scanner.nextDouble();
// TODO: Create a ReportGenerator with the title and call generateDocument()
// TODO: Print an empty line for separation
// TODO: Create an InvoiceGenerator with customer name and amount, and call generateDocument()
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System9Generics
Introduction to GenericsGeneric ClassesGeneric MethodsBounded Type ParametersWildcards (?, extends, super)Recap - Generic Container12Design Patterns Part 2
Command PatternAdapter PatternDecorator PatternTemplate Method PatternState PatternComposite PatternIterator Pattern