Template Method Design Pattern in Java: Complete Guide with Real-World Examples
Have you ever noticed that different payment methods follow almost the same process?
For example, whether a customer makes a payment using UPI, a debit card, or a wallet, the application generally performs these steps:
- Validate the payment request.
- Check payment conditions.
- Execute the payment.
- Save the transaction details.
- Send a notification.
The overall payment process remains almost the same, but the actual payment execution changes depending on the payment method.
Now imagine writing this complete workflow separately for every payment method. You would probably end up with duplicated code.
The Template Method Design Pattern in Java solves exactly this problem. It defines the overall algorithm in a parent class and allows subclasses to customize individual steps.
In this guide, we will understand the pattern using a tea-and-coffee example and a real-world payment processing scenario, implement complete executable Java code, explore a Spring Boot use case, compare it with Strategy, and prepare for common Java design-pattern interview questions.
1. What Is the Template Method Design Pattern?
The Template Method pattern is a behavioral design pattern that defines the skeleton of an algorithm in a superclass. Some steps are implemented in the parent class, while other steps are left to subclasses.
The important point is that the parent class controls the execution order.
In simple words: The parent class decides what happens and in which order. The child class decides how certain steps happen.
Real-world example: Preparing tea and coffee
Think about preparing tea and coffee. Both follow a common process:
- Boil water.
- Add the main ingredient.
- Add milk or other ingredients.
- Serve the drink.
However, the ingredients are different. For tea, we add tea leaves. For coffee, we add coffee powder. The overall preparation process remains the same, but certain steps change.
This is the basic idea behind the Template Method Pattern.
Key participants
- Abstract Class: Defines the template method and common steps.
- Template Method: Defines the fixed sequence of operations.
- Concrete Class: Implements the steps that vary.
- Hook Method: An optional method with a default implementation that subclasses can override.
2. Important Components of the Pattern
The pattern has four key building blocks.
1. Abstract Class
Defines the template method and common steps. It may declare abstract methods for steps that subclasses must provide and concrete methods for steps that are shared.
2. Template Method
Defines the fixed sequence of operations. It usually calls common
methods, abstract methods, and optional hook methods in a specific
order. Making it final prevents subclasses from changing
the sequence.
3. Concrete Class
Implements the steps that vary between different variants of the
algorithm. For example, UPIPayment,
CardPayment, and WalletPayment provide their
own executePayment() implementations.
4. Hook Method
An optional method that subclasses can override to customize a step. It has a default implementation in the parent class, so subclasses that do not need customization can simply ignore it.
3. Template Method Class Diagram
This original diagram shows how an abstract payment class defines the common workflow, while UPI, card, and wallet payment classes provide their own payment implementation.
Important: The abstract class contains the common
workflow. Each child class provides its own implementation of
executePayment(). The wallet class can additionally
override the optional hook method.
4. How the Template Method Works Internally
Let's understand the execution sequence.
- The client creates an object of a concrete payment class.
- The client calls
processPayment(). - The parent class validates the payment request.
- The parent class calls
beforePayment(). - The child class implementation of
executePayment()is invoked. - The parent class saves the transaction and sends a notification.
The important point is that the client never assembles the workflow itself. The parent class owns the sequence, and the subclass only supplies the pieces that differ.
What changes after introducing a template method?
The common steps live in one place. Each concrete subclass contains only the implementation of the specific steps that vary. Adding a new payment method becomes a matter of adding a new subclass rather than duplicating the whole workflow.
5. Execution Flow Diagram
This diagram represents the common sequence followed by UPI, card, and wallet payments. Only the payment execution implementation changes.
The parent class controls the sequence before and after payment execution. The child class only supplies the payment-specific behavior.
6. Java Implementation – Tea and Coffee Example
Before implementing a payment system, let's create a simple example using tea and coffee. This example makes the pattern easy to see before applying it to a real workflow.
Complete executable Java code
Create a file named BeverageDemo.java and copy the following code.
abstract class Beverage {
// Template Method
public final void prepareBeverage() {
boilWater();
addMainIngredient();
addCondiments();
serve();
}
private void boilWater() {
System.out.println("Boiling water...");
}
protected abstract void addMainIngredient();
protected abstract void addCondiments();
private void serve() {
System.out.println("Serving beverage...");
}
}
class Tea extends Beverage {
@Override
protected void addMainIngredient() {
System.out.println("Adding tea leaves...");
}
@Override
protected void addCondiments() {
System.out.println("Adding milk and sugar...");
}
}
class Coffee extends Beverage {
@Override
protected void addMainIngredient() {
System.out.println("Adding coffee powder...");
}
@Override
protected void addCondiments() {
System.out.println("Adding milk and sugar...");
}
}
public class BeverageDemo {
public static void main(String[] args) {
Beverage tea = new Tea();
System.out.println("Preparing Tea:");
tea.prepareBeverage();
System.out.println();
Beverage coffee = new Coffee();
System.out.println("Preparing Coffee:");
coffee.prepareBeverage();
}
}
Expected output
Preparing Tea:
Boiling water...
Adding tea leaves...
Adding milk and sugar...
Serving beverage...
Preparing Coffee:
Boiling water...
Adding coffee powder...
Adding milk and sugar...
Serving beverage...
Understand this carefully: Both classes execute the
same prepareBeverage() method. However, the implementation
of addMainIngredient() and addCondiments()
comes from the respective child class.
Also notice the final keyword. It prevents subclasses from
overriding the template method and changing the overall sequence.
7. Real-World Example – Payment Processing System
Now let's understand a practical example from a fintech application.
Suppose you are developing a payment gateway that supports three payment methods:
- UPI payment
- Debit or credit card payment
- Wallet payment
All three methods need common processing steps, but each payment method has its own execution logic. Without a proper design, developers may write the same validation, transaction-saving, and notification code in multiple classes.
Let's solve this problem using the Template Method Pattern.
Complete executable Java 8 code
For simplicity, we will simulate the payment providers using console messages. In a real application, the payment execution methods would communicate with external payment APIs or internal payment services.
Create a file named PaymentDemo.java.
abstract class AbstractPayment {
private final double amount;
public AbstractPayment(double amount) {
this.amount = amount;
}
// Template Method
public final void processPayment() {
validatePayment();
beforePayment();
executePayment();
saveTransaction();
sendNotification();
System.out.println("Payment completed successfully.");
}
private void validatePayment() {
if (amount <= 0) {
throw new IllegalArgumentException(
"Payment amount must be greater than zero"
);
}
System.out.println("Payment validation successful.");
}
// Optional hook method
protected void beforePayment() {
System.out.println("Checking payment conditions...");
}
// Subclasses implement their own payment logic
protected abstract void executePayment();
private void saveTransaction() {
System.out.println("Saving transaction: Rs. " + amount);
}
private void sendNotification() {
System.out.println("Sending payment notification...");
}
protected double getAmount() {
return amount;
}
}
class UPIPayment extends AbstractPayment {
public UPIPayment(double amount) {
super(amount);
}
@Override
protected void executePayment() {
System.out.println(
"Processing UPI payment of Rs. " + getAmount()
);
}
}
class CardPayment extends AbstractPayment {
public CardPayment(double amount) {
super(amount);
}
@Override
protected void executePayment() {
System.out.println(
"Processing Card payment of Rs. " + getAmount()
);
}
}
class WalletPayment extends AbstractPayment {
public WalletPayment(double amount) {
super(amount);
}
@Override
protected void beforePayment() {
System.out.println("Checking wallet balance...");
}
@Override
protected void executePayment() {
System.out.println(
"Processing Wallet payment of Rs. " + getAmount()
);
}
}
public class PaymentDemo {
public static void main(String[] args) {
System.out.println("----- UPI PAYMENT -----");
AbstractPayment upiPayment =
new UPIPayment(1000);
upiPayment.processPayment();
System.out.println();
System.out.println("----- CARD PAYMENT -----");
AbstractPayment cardPayment =
new CardPayment(2000);
cardPayment.processPayment();
System.out.println();
System.out.println("----- WALLET PAYMENT -----");
AbstractPayment walletPayment =
new WalletPayment(500);
walletPayment.processPayment();
}
}
Let's understand the important code
1. Why is processPayment() final?
The processPayment() method is the template method. It
defines the payment workflow. Making it final prevents
subclasses from overriding the method and changing the required
execution sequence.
2. Why is executePayment() abstract?
Because each payment method has a different implementation. UPI, card, and wallet payments may communicate with different services or providers.
3. Why is beforePayment() a hook method?
Not every payment method needs the same additional operation. The parent class provides a default implementation, and a child class can override it when necessary. In our example, the wallet payment checks its balance before executing the payment.
4. Why are saveTransaction() and sendNotification() common methods?
Because the basic transaction-saving and notification workflow is shared by all payment types in this simplified example. Therefore, we avoid duplicating these operations in every child class.
8. Payment Workflow Diagram
This original diagram shows the shared payment template and the three concrete payment implementations that plug into it.
9. Expected Output
----- UPI PAYMENT -----
Payment validation successful.
Checking payment conditions...
Processing UPI payment of Rs. 1000.0
Saving transaction: Rs. 1000.0
Sending payment notification...
Payment completed successfully.
----- CARD PAYMENT -----
Payment validation successful.
Checking payment conditions...
Processing Card payment of Rs. 2000.0
Saving transaction: Rs. 2000.0
Sending payment notification...
Payment completed successfully.
----- WALLET PAYMENT -----
Payment validation successful.
Checking wallet balance...
Processing Wallet payment of Rs. 500.0
Saving transaction: Rs. 500.0
Sending payment notification...
Payment completed successfully.
Notice that all three payments execute the same
processPayment() template, but the
executePayment() step changes for each payment method. The
wallet payment also overrides the beforePayment() hook to
check the balance.
How the responsibilities are separated
| Component | Responsibility |
|---|---|
AbstractPayment |
Defines the workflow and common steps. |
processPayment() |
Fixed template method controlling the execution sequence. |
executePayment() |
Abstract step implemented by each concrete payment class. |
beforePayment() |
Optional hook overridable by subclasses when needed. |
UPIPayment / CardPayment / WalletPayment |
Provide their own execution logic. |
10. Template Method in Spring Boot
The Template Method Pattern can be useful in Spring Boot applications when multiple services follow a common sequence of operations but have different implementations for one or more steps.
Some examples include:
- Payment processing: Common validation, transaction handling, and notification workflow.
- File processing: Read file, validate records, transform data, and save results.
- Report generation: Load data, process records, generate a report, and export it.
- Authentication: Common authentication flow with different authentication mechanisms.
- Third-party integration: Common request preparation, provider-specific execution, and response handling.
Example: Spring Boot file processing
Suppose your Spring Boot application processes CSV and Excel files. Both file types follow a similar workflow:
- Read the file.
- Validate its contents.
- Transform the data.
- Save the records.
You can create an abstract processor that defines this workflow and separate CSV and Excel processors that implement the file-specific steps. This keeps common processing logic in one place.
Is this always the best design?
No. A class hierarchy is not always the right answer. If the workflow itself needs to change frequently, or if you need to select an algorithm at runtime, the Strategy pattern may be a better fit.
Production consideration: In a real Spring Boot application, also consider dependency injection, transaction boundaries, exception handling, retry policies, idempotency, and external API failure handling. A template method alone does not provide these capabilities.
11. Template Method vs Strategy Pattern
Both patterns help reduce duplicated code, but they solve different problems.
| Comparison | Template Method | Strategy |
|---|---|---|
| Type | Behavioral | Behavioral |
| Approach | Inheritance | Composition |
| Algorithm | Defines a fixed workflow | Encapsulates interchangeable algorithms |
| Customization | Subclasses override steps | Different strategy implementations |
| Execution order | Controlled by parent class | Controlled by the calling object |
| Flexibility | Suitable for fixed workflows | Flexible for runtime selection |
Template Method: Every payment follows the same sequence, but the payment execution step changes.
Strategy: The application selects a payment strategy, such as UPI, card, or wallet, and delegates payment execution to that strategy.
Template Method uses inheritance to vary individual steps of an algorithm. Strategy uses composition to replace an entire algorithm.
12. Advantages and Disadvantages of the Template Method Pattern
Advantages
- Code reusability: Common logic is written once in the parent class.
- Less code duplication: Subclasses implement only the steps that differ.
- Consistent workflow: The parent class controls the sequence of operations.
- Easy maintenance: Changes to common operations can be made in one place.
- Controlled customization: Subclasses can customize only the permitted steps.
Disadvantages
- Inheritance dependency: It relies on a parent-child relationship, which creates tight coupling.
- Limited flexibility: Changing the workflow may require modifying the parent class.
- More subclasses: Multiple variations can increase the number of classes.
- Debugging complexity: Execution moves between parent and child methods, which can make debugging harder.
- Subclass coupling: Child classes depend on the structure and protected methods of the parent class.
The best template method is small, focused, and stable. If the workflow begins to change frequently or needs to be selected at runtime, consider moving to a composition-based design instead.
13. Best Practices
- Keep the template method small and easy to understand. The sequence of steps should be readable at a glance.
-
Use the
finalkeyword when subclasses must not change the algorithm sequence. - Keep common operations in the parent class. Avoid duplicating the same logic in each subclass.
- Use abstract methods only for steps that must be implemented by subclasses.
- Use hook methods for optional customization. Provide sensible defaults so subclasses can override only when necessary.
- Avoid adding too many customization points without a real requirement. More hooks increase complexity without adding value.
- Do not use inheritance just to share a few utility methods. Composition is usually a better fit for that case.
- Write unit tests for the common workflow and each concrete implementation. This ensures the sequence remains intact as the design evolves.
14. Java Interview Questions and Answers
Q1. What is the Template Method Design Pattern?
Template Method is a behavioral design pattern that defines the skeleton of an algorithm in a superclass and allows subclasses to implement or customize specific steps without changing the overall algorithm structure.
Q2. Why is Template Method called a behavioral design pattern?
Because it focuses on how an algorithm is executed and how responsibilities are distributed between the parent and child classes.
Q3. What is a template method?
A template method is the method that defines the sequence of steps of an algorithm. It usually calls common methods, abstract methods, and optional hook methods.
Q4. Why is the template method often declared final?
To prevent subclasses from overriding the workflow and changing the predefined order of execution. However, declaring it final is a design choice, not an absolute requirement of the pattern.
Q5. What is a hook method?
A hook method is an optional method with a default implementation in the parent class. Subclasses can override it to customize behavior when required.
Q6. What is the difference between an abstract method and a hook method?
An abstract method has no implementation in the abstract class and must be implemented by a concrete subclass. A hook method has a default implementation and can optionally be overridden.
Q7. Can we implement Template Method without an abstract class?
Yes. A concrete parent class can define the template method and allow subclasses to override protected methods. However, an abstract class is commonly used when some algorithm steps must be implemented by subclasses.
Q8. What is the difference between Template Method and Strategy?
Template Method uses inheritance and defines a fixed algorithm structure. Strategy uses composition and allows the application to select an interchangeable algorithm implementation.
Q9. Can a template method call private methods?
Yes. The template method can call private methods for operations that must remain internal to the parent class. Subclasses cannot override those private methods.
Q10. Can a subclass change the execution order?
If the template method is final, the subclass cannot override the workflow. It can only customize the steps that the parent class exposes for customization.
Q11. What is the Hollywood Principle in relation to Template Method?
The Hollywood Principle means "Don't call us, we'll call you." The parent class controls the algorithm and calls the subclass methods when necessary. Subclasses do not control the overall workflow.
Q12. Is Template Method suitable for microservices?
It can be useful inside a microservice when multiple workflows share common steps. For example, different file processors or payment handlers may share a common processing sequence. It does not replace communication or orchestration between microservices.
Q13. Can Template Method be used with Spring Boot?
Yes. An abstract Spring-managed service can define a common workflow, while concrete Spring components implement the specific steps. Dependency injection can be used for supporting services.
Q14. What happens if a subclass does not implement an abstract method?
The subclass must either implement the abstract method or remain abstract. Otherwise, Java compilation fails.
Q15. When should we avoid Template Method?
Avoid it when the steps of the algorithm change frequently, when you need to select algorithms dynamically at runtime, or when inheritance creates unnecessary coupling. Strategy or composition may be a better choice in such cases.
15. Frequently Asked Questions
Is Template Method part of Java?
No. It is a design pattern, not a built-in Java API. You can implement it using Java classes, inheritance, and method overriding.
Is Template Method the same as a Java template class?
No. Java does not have C++-style templates. Template Method is a design pattern implemented through inheritance and polymorphism.
Can we use interfaces for Template Method?
An interface with default methods can provide some similar behavior, but an abstract class is generally more suitable when you need shared state, constructors, protected methods, and abstract steps.
Where is Template Method useful in real projects?
It is useful in payment processing, file processing, report generation, authentication workflows, and third-party integrations where the overall sequence is common but individual steps differ.
Is the Template Method pattern part of the Gang of Four patterns?
Yes. Template Method is one of the behavioral patterns in the Gang of Four design-pattern catalog.
Does Template Method mean all steps must be fixed?
No. The sequence is fixed, but individual steps can be implemented, overridden, or optionally skipped through hooks depending on the design.
16. Quick Revision Checklist
- Template Method is a behavioral design pattern.
- It defines the skeleton of an algorithm in a superclass.
- The template method controls the execution order.
- Subclasses customize specific steps without changing the sequence.
- Making the template method
finalprotects the workflow. - Hook methods provide optional customization with sensible defaults.
- Payment processing, file processing, and report generation are typical uses.
- Template Method uses inheritance; Strategy uses composition.
- Spring Boot services can use it for common workflows across concrete components.
- Avoid it when the workflow changes frequently or must be selected at runtime.
Conclusion
The Template Method Design Pattern is useful when multiple classes follow the same algorithm but need different implementations for certain steps. Instead of duplicating the entire workflow, we define the common sequence in a parent class and let subclasses customize only the required operations.
Remember these three important points:
- The parent class defines the algorithm structure.
- Child classes customize specific steps.
- The template method controls the execution order.
Before using this pattern in a real project, check whether your workflow is genuinely common. If the entire algorithm needs to change dynamically, consider the Strategy Pattern instead.
If you are preparing for Java interviews, practise implementing Template Method alongside Strategy, Observer, and Factory Method. Understanding when each pattern is useful matters more than memorizing its definition.
No comments:
Post a Comment