Thursday, January 29, 2015

Template Method Design Pattern

Template Method Design Pattern in Java

Introduction

Over the course of this article, we will examine Template  Method design pattern in java with help of realtime examples.
The template method design pattern belongs to the behavioural family of patterns that defines the steps for an algorithm and allows subclass to provide implementation for one or more steps. This design pattern helps in maximizing the code reusability.

How Template Method Works?

  1. Define an abstract base class with some fully qualified method containing common implementation logic
  2. Declare the abstract methods for subclasses to override specific behaviours
  3. Declare a Template method in superclass that holds the core algorithm implementation steps
  4. Derived classes can override placeholder methods
  5. Derived classes can override implemented methods

Real Time Use Case

Let us take the example of a Pizza Store. The making of a Pizza includes the steps such as selection of bread, add ingredient, heating, add toppings and add cheese. All this steps are in sequential order. Let us implement this use case in Template Method design representation.

Class Diagram

Template Method Design Pattern Example
The above use case is represented in the following class diagram.
  1. We have declares an abstract base class for all Pizza implementation. The Pizza store currently serves two variants of pizzas; SweetCornPizza and MexicanPizza. Both classes extends Pizza class.
  2. Pizza class contains the chooseBread(), addIngredients() abstract methods. Each of the Pizza implementation will override them to provide specific implementation logic.
  3. The heating(), addTopinngs() and addCheese() methods are common for all Pizza types and hence their implementation is commonly provided in Pizza super class.
  4. Pizza superclass defines preparePizza() template method that controls the order that all other methods are called.
  5. Note that preparePizza() method is declared as final, because we don’t want client to override/change the pizza preperation  steps.
Thats all! We are ready with Template Method design. Lets us have a glance at the code snippet below.

Pizza.java

public abstract class Pizza {
public abstract void chooseBread();
public abstract void addIngredients();

public void heating() {
System.out.println("Heating for 10 minutes!");
}

public void addTopinngs() {
System.out.println("Adding Topinngs!");
}

public void addCheese() {
System.out.println("Adding Cheese!");
}

// Template method
public final void preparePizza() {
chooseBread();
addIngredients();
heating();
addCheese();
addTopinngs();
}
}

SweetCornPizza.java

public class SweetCornPizza extends Pizza {
@Override
public void chooseBread() {
System.out.println("Choosing SweetCorn Pizza Bread!");
}

@Override
public void addIngredients() {
System.out.println("Adding SweetCorn Pizza Ingredients!");
}
}

MexicanPizza.java

public class MexicanPizza extends Pizza {
@Override
public void chooseBread() {
System.out.println("Choosing Mexican Pizza Bread!");
}

@Override
public void addIngredients() {
System.out.println("Adding Mexican Pizza Ingredients!");
}
}

TestMain.java

public class TestMain {
public static void main(String[] args) {
SweetCornPizza pizza1 = new SweetCornPizza();
pizza1.preparePizza();

System.out.println("**********");

MexicanPizza pizza2 = new MexicanPizza();
pizza2.preparePizza();
}
}

Output

Adding SweetCorn Pizza Ingredients!
Heating for 10 minutes!
Adding Cheese!
Adding Toppings!
************
Choosing Mexican Pizza Bread!
Adding Mexican Pizza Ingredients!
Heating for 10 minutes!
Adding Cheese!
Adding Toppings!

Things to Know

  1. The Template method should be declares as final to avoid its subclass overriding its implementation logic.
  2. The template method in a super class follows the Hollywood principle, Don’t call us, we’ll call you. This refers to the fact that instead of calling the base class methods in the subclasses, the methods from the subclass are called form super class template method.

Problem – 1

So far our pizza store works great. But now based on the customer demand the Pizza store is willing to introduce two new pizza types DoubleCheesePizza and NoCheesePizza.

Adding Hook Methods

In Order to support Double Cheese Pizza, we can override the addCheese() method in DoubleCheesePizza class and provide double cheese specific implementation here.

DoubleCheesePizza.java

public class DoubleCheesePizza extends Pizza {
@Override
public void chooseBread() {
System.out.println("Choosing DoubleCheese Pizza Bread!");
}

@Override
public void addIngredients() {
System.out.println("Adding DoubleCheese Pizza Ingredients!");
}

@Override
public void addCheese() {
System.out.println("Adding Double Cheese!");
}
}
However, for No cheese pizza the current design will fail to support. We have to introduce a hook methods to achieve the same.
  1. Add isCheese() method in Pizza class that execute addCheese() method conditionally.
  2. Change the following code in preparePizza() method.
public boolean isCheese(){
return true;
}

// Template method
public final void preparePizza() {
chooseBread();
addIngredients();
heating();

if(isCheese()){
   addCheese();
}
addTopinngs();
}

NoCheesePizza.java

public class NoCheesePizza extends Pizza {
@Override
public void chooseBread() {
System.out.println("Choosing SweetCorn Pizza Bread!");
}

@Override
public void addIngredients() {
System.out.println("Adding SweetCorn Pizza Ingredients!");
}

@Override
public boolean isCheese() {
return false;
}
}

No comments:

Post a Comment