Template Method Pattern
The Template Method Pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
Template Method Pattern Diagram

Implementation
Creating an Abstract Class:
public abstract class CaffeineBeverage {
/* Template Method */
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
/* Primitive Methods */
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
/* Hook
Subclass can choose either to implmenent it or not */
boolean customerWantsCondiments() {
return true;
}
}Creating a Concrete Class:
public class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("Dripping Coffee through filter");
}
public void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
/* Overrding Hook */
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
private String getUserInput() {
String answer = null;
System.out.print("Would you like milk and sugar with your coffee (y/n)? ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException ioe) {
System.err.println("IO error trying to read your answer");
}
if (answer == null) {
return "no";
}
return answer;
}
}Testing:
public class BeverageTestDrive {
public static void main(String[] args) {
Tea teaHook = new Tea();
Coffee coffeeHook = new Coffee();
System.out.println("\nMaking tea...");
teaHook.prepareRecipe();
System.out.println("\nMaking coffee...");
coffeeHook.prepareRecipe();
}
}Real Example
Creating a Concrete class that implements Comparable template:
public class Duck implements Comparable<Duck> {
String name;
int weight;
public Duck(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String toString() {
return name + " weighs " + weight;
}
/* Hook */
public int compareTo(Duck otherDuck) {
if (this.weight < otherDuck.weight) {
return -1;
} else if (this.weight == otherDuck.weight) {
return 0;
} else { // this.weight > otherDuck.weight
return 1;
}
}
}Testing:
public class DuckSortTestDrive {
public static void main(String[] args) {
Duck[] ducks = {
new Duck("Daffy", 8),
new Duck("Dewey", 2),
new Duck("Howard", 7),
new Duck("Louie", 2),
new Duck("Donald", 10),
new Duck("Huey", 2)
};
System.out.println("Before sorting:");
display(ducks);
Arrays.sort(ducks);
System.out.println("\nAfter sorting:");
display(ducks);
}
public static void display(Duck[] ducks) {
for (Duck d : ducks) {
System.out.println(d);
}
}
}