The Template Method pattern is a behavioral design pattern that defines the skeleton of an algorithm in a superclass but lets subclasses override specific steps of the algorithm without changing its structure. In this pattern, the overall structure of the algorithm is preserved while allowing subclasses to customize the implementation of certain steps.
In this article, we will discuss how to implement the Template Method pattern in Java.
Structure of the Template Method pattern
The Template Method pattern consists of the following components:
Abstract class: Defines the overall algorithm and contains one or more abstract methods that will be implemented by subclasses.
Concrete class: Implements the abstract methods defined in the abstract class.
Template Method: Defines the algorithm’s skeleton and calls the abstract methods in the abstract class.
Example of Template Method pattern in Java
Let’s take an example of a coffee and tea making application. The overall algorithm for making coffee and tea is the same, but the specific steps for brewing each drink are different. We can implement the Template Method pattern to define the algorithm’s skeleton and allow subclasses to override specific steps.
Here’s how we can implement the Template Method pattern in Java for our coffee and tea making application:
public abstract class CaffeineBeverage {
// Template method
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
addCondiments();
}
// Abstract methods
protected abstract void brew();
protected abstract void addCondiments();
// Concrete methods
private void boilWater() {
System.out.println("Boiling water");
}
private void pourInCup() {
System.out.println("Pouring into cup");
}
}
In this example, we define an abstract class CaffeineBeverage that contains the overall algorithm for making a caffeine beverage. The prepareBeverage method is the Template Method that defines the algorithm’s skeleton.
The brew and addCondiments methods are abstract methods that will be implemented by subclasses. These methods define the specific steps for brewing each type of caffeine beverage.
The boilWater and pourInCup methods are concrete methods that are shared by both coffee and tea making algorithms.
Next, we’ll create concrete classes for making coffee and tea:
public class Coffee extends CaffeineBeverage {
@Override
protected void brew() {
System.out.println("Dripping coffee through filter");
}
@Override
protected void addCondiments() {
System.out.println("Adding sugar and milk");
}
}
public class Tea extends CaffeineBeverage {
@Override
protected void brew() {
System.out.println("Steeping the tea");
}
@Override
protected void addCondiments() {
System.out.println("Adding lemon");
}
}
In these concrete classes, we override the brew and addCondiments methods to define the specific steps for making coffee and tea.
Finally, we can use the concrete classes to make coffee and tea:
CaffeineBeverage coffee = new Coffee();
coffee.prepareBeverage();
CaffeineBeverage tea = new Tea();
tea.prepareBeverage();
In this example, we create instances of the Coffee and Tea classes and call the prepareBeverage method to make coffee and tea. The prepareBeverage method calls the abstract methods brew and addCondiments defined in the subclasses to customize the algorithm’s specific steps.