What is Template method pattern?
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.
When to use it?
- Use Template method pattern when you have classes that contains similar algorithms with minor differences.
Problem
Let's say we create classes represents animal behavior. Our first version of implementation is below:
Dog and Bird, they both wake up in the morning and sleep in the night, but eat different things. Our superclass Animal defines common methods for all animals such as wakeUp()
and sleep()
, but doDailyRoutine()
method is declared as abstract and we delegate its implementation to subclasses because it is vary for each animal.
public abstract class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public abstract void doDailyRoutine();
public void wakeUp() {
System.out.println(name + " wakes up in the morning.");
}
public void sleep() {
System.out.println(name + " sleeps in the night.");
}
}
public class Bird extends Animal {
public Bird(String name) {
super(name);
}
@Override
public void doDailyRoutine() {
wakeUp();
eatFruit();
sleep();
}
public void eatFruit() {
System.out.println(name + " eats a fruit.");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void doDailyRoutine() {
wakeUp();
eatDogFood();
sleep();
}
public void eatDogFood() {
System.out.println(name + " eats dog food.");
}
}
The problem we have is eatFruit
and eatDogFood
methods. Despite of different kinds of foods, they both do the same thing, eating. For just one slight difference, we need to write doDailyRoutine
method in subclasses over and over. So we should pull up abstraction level to get rid of code duplication.
Also, animals may have their own behavior. We'll see how we can make a room for additional behavior, yet still reduces code duplication.
Solution
Animal
Instead of definingdoDailyRoutine
in subclasses, we define it in superclassAnimal
. All animals exactly follow the order, that is,wakeUp
,eat
,sleep
.eat
method is declared as abstract because each animal eats different things.
additionalBehavior
has empty body, so it does nothing. However, we can override the method in subclasses if some animal have unique behavior. This kind of method is called hook in Template method pattern.Animal subclasses
Although animal subclasses can't change algorithm structure, they can override some of the step methods used bydoDailyRoutine()
. Also, they can optionally add additional behavior by overriding the hook method.
Structure
Implementation in Java
public abstract class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
// TemplateMethod is final to prevent subclasses changes its structure
public final void doDailyRoutine() {
wakeUp();
additionalBehavior();
eat();
sleep();
}
public void wakeUp() {
System.out.println(name + " wakes up in the morning.");
}
public abstract void eat();
public void sleep() {
System.out.println(name + " sleeps in the night.");
}
public void additionalBehavior() {
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(name + " eats dog food.");
}
@Override
public void additionalBehavior() {
System.out.println(name + " gets cuddled.");
}
}
public class Bat extends Animal {
public Bat(String name) {
super(name);
}
@Override
public void wakeUp() {
System.out.println(name + " wakes up in the night.");
}
@Override
public void eat() {
System.out.println(name + " eats insects.");
}
@Override
public void sleep() {
System.out.println(name + " sleeps in the morning.");
}
}
public class AnimalTestDrive {
public static void main(String[] args) {
Animal bird = new Bird("Pigeon");
Animal dog = new Dog("Golden retriever");
Animal bat = new Bat("Silver-haired bat");
bird.doDailyRoutine();
System.out.println();
dog.doDailyRoutine();
System.out.println();
bat.doDailyRoutine();
}
}
Output:
Pigeon wakes up in the morning.
Pigeon sings.
Pigeon eats fruits.
Pigeon sleeps in the night.
Golden retriever wakes up in the morning.
Golden retriever gets cuddled.
Golden retriever eats dog food.
Golden retriever sleeps in the night.
Silver-haired bat wakes up in the night.
Silver-haired bat eats insects.
Silver-haired bat sleeps in the morning.
Pitfalls
- Algorithm implementations can be spread over multiple subclasses making it hard to maintain.
- Granularity and flexibility are tradeoff relationship. If AbstractClass have many abstract methods, it offers more flexibility but we'll have more burden in subclasses.
You can check all the design pattern implementations here.
GitHub Repository
Top comments (0)