Behavioral Design Patterns provide solution for the better interaction between objects and how to provide lose coupling and flexibility to extend easily. Following design patterns come under this category.
Template method defines the skeleton of how a certain algorithm could be performed, but defers the implementation of those steps to the children classes.
A Template method defines an algorithm in a base class using abstract operations that subclasses override to provide concrete behavior.
The Template method pattern can be used in situations when there is an algorithm, some steps of which could be implemented in multiple different ways. In such scenarios, the Template method pattern suggests keeping the outline of the algorithm in a separate method referred to as a template method inside a class, which may be referred to as a template class, leaving out the specific implementations of the variant portions (steps that can be implemented in multiple different ways) of the algorithm to different subclasses of this class.
The Template method does not necessarily have to leave the implementation to subclasses in its entirety. Instead, as part of providing the outline of the algorithm, the Template class can also provide some amount of implementation that can be considered as invariant across different implementations. It can even provide default implementation for the variant parts, if appropriate. Only specific details will be implemented inside different subclasses. This type of implementation eliminates the need for duplicate code, which means a minimum amount of code to be written.
Intents of Template method are
Components:
When to use the Template method pattern:
Rules of thumb:
Here is an example of the Template method pattern. Meal
is an abstract class with a template method called doMeal()
that defines the steps involved in a meal. We declare the method as final so that it can't be overridden. The algorithm defined by doMeal()
consists of four steps: prepareIngredients()
, cook()
, eat()
, and cleanUp()
. The eat()
method is implemented although subclasses can override the implementation. The prepareIngredients()
, cook()
, and cleanUp()
methods are are declared abstract so that subclasses need to implement them.
Java
File Meal.java.
public abstract class Meal { // template method public final void doMeal() { prepareIngredients(); cook(); eat(); cleanUp(); } public abstract void prepareIngredients(); public abstract void cook(); public void eat() { System.out.println("Mmm, that's good"); } public abstract void cleanUp(); }
File HamburgerMeal.java.
public class HamburgerMeal extends Meal { @Override public void prepareIngredients() { System.out.println("Getting burgers, buns, and french fries"); } @Override public void cook() { System.out.println("Cooking burgers on grill and fries in oven"); } @Override public void cleanUp() { System.out.println("Throwing away paper plates"); } }
File TacoMeal.java.
public class TacoMeal extends Meal { @Override public void prepareIngredients() { System.out.println("Getting ground beef and shells"); } @Override public void cook() { System.out.println("Cooking ground beef in pan"); } @Override public void eat() { System.out.println("The tacos are tasty"); } @Override public void cleanUp() { System.out.println("Doing the dishes"); } }
File Demo.java.
public class Demo { public static void main(String[] args) { Meal meal1 = new HamburgerMeal(); meal1.doMeal(); System.out.println(); Meal meal2 = new TacoMeal(); meal2.doMeal(); } }
Python 3
import abc class Meal(metaclass=abc.ABCMeta): # template method def do_meal(self): self.prepare_ingredients() self.cook() self.eat() self.clean_up() def eat(self): print("Mmm, that's good") @abc.abstractmethod def prepare_ingredients(self): pass @abc.abstractmethod def cook(self): pass @abc.abstractmethod def clean_up(self): pass class HamburgerMeal(Meal): def prepare_ingredients(self): print("Getting burgers, buns, and french fries") def cook(self): print("Cooking burgers on grill and fries in oven") def clean_up(self): print("Throwing away paper plates") class TacoMeal(Meal): def prepare_ingredients(self): print("Getting ground beef and shells") def cook(self): print("Cooking ground beef in pan") def eat(self): print("The tacos are tasty") def clean_up(self): print("Doing the dishes") if __name__ == '__main__': meal1 = HamburgerMeal() meal1.do_meal() print("-----") meal2 = TacoMeal() meal2.do_meal() print("-----")