In this article we are going to learn about a very easy pattern , Template Method Design Pattern.

  • What is Template Method design pattern?
  • What are the basic principles?
  • How to implement
  • where we can use this. I have used Java with Eclipse and C# with VS2010.

What is Template Method design pattern?

Template method design pattern used to create a group of sub classes that have to execute a similar group of methods.

Let’s assume we are making burgers. A burger making process is same but based on type, it more items will be added. Like, I want vegetable , you may want buff burger, another one may want only eggs in the burger. We can apply template like, keeping the burger making formula in super class and extending classes will override the item adding methods conditionally.

Or, lets think of making a set of puzzle(similar type, chess, monopoly) where our main structure like initialization, collecting bets, making play, ending game, providing winner, espouse looser , providing price to winner. those process are same. So, we can keep those in a template method in a abstract class and extend that to chess or monopoly class.

In Template Method, there are 3 Basic Item

  • Template method
  • Template method containing abstract base class
  • Sub Classes who may change inner implementations.

We will know more over code.

Principles :

  • Define the skeleton of an working process in an operation which will be organized by sub classes.
  • Let the sub classes re define certain steps of the working process without changing the skeleton of target working process.

UML :

uml-template

How to implement?

An abstract class will be there who contains the skeleton.

That skeleton will be inside a method act as Template Method and we need to protect that template method from changing by any of subclasses(not be overridden).

The template method contains a series of method calls that every sub class will call. Sub class can override any method call only.

  • An abstract class containing a template method.
  • Template method which we need to protect to keep safe form changing. (in example,I made that as final)
  • The template method will contain skeleton of working progress. which will be used by all sub classes
  • In the template method, we need some kind of Hook. It refers to a Boolean output method defines which steps to be executed by each sub classes.(Detail explanation in the example)

Example :

  • Let’s assume a Loan Sanction Procedure on different type of loans.
    1. House Loan
    2. Consumer Loan
    3. Study Loan
  • And, for each loan type we need to go through some process to sanction the loan. Like as , for house loan, we need to check property(which is mortgaged) and Bank solvency.
  • And, for consumer loan, we need to check customer’s all account’s statements(last 6 months), employment status and business status.
  • And finally for study loan, we need to check person’s bank solvency.

We will also need a client who will call this loans.

So, lets start with the abstract class Loan, who will have the final template method provideLoan() along with hooks.

public abstract class Loan {
    public abstract void checkAllAccountStatement() ;
    public abstract void checkBankSolvency() ;
    public abstract void checkBusiness() ;
    public abstract void checkEmployment();
    public abstract void checkPeoperty() ;    
public final void provideLoan()//the template method
    {
        createBankAccount();        
        if(needCheckProperty()){
            checkPeoperty();
        }
        if(needCheckEmployment()){
            checkEmployment();
        }
        if(needCheckBusiness()){
            checkBusiness();        }
        if(needCheckBankSolvency()){
            checkBankSolvency();
        }
        if(needCheckAllAccountStatement()){
            checkAllAccountStatement();
        }        
        keepAllMonthlyInstallmentChecks();
        sendConfirmation();
    }
    public void sendConfirmation() {
        System.out.println("A loan has been sanctioned");        
    }
    public void keepAllMonthlyInstallmentChecks() {
        System.out.println("Taking all signed checks for monthly installments");        
    }    
    public void createBankAccount(){
        System.out.println("An account has been created for the loan ");
    }
    //the hooks
    public boolean needCheckProperty(){return true;}
    public boolean needCheckBankSolvency(){return true;}
    public boolean needCheckAllAccountStatement(){return true;}
    public boolean needCheckEmployment(){return true;}
    public boolean needCheckBusiness(){return true;}
}

In here, there are 5 hooks(returned all true in super class) are used which apply the condition of execution of each method derived in sub classes.

Now, individual Loan classes who actually apply those. In loan class we will do mainly

  1. Implement the methods which are applicable
  2. Keeping not necessary method as empty.
  3. Make the hooks return false for the checking that we do not need.

That means, if home loan need to check property & solvency then all other hooks will be returning false (and only property & solvency checking method will be implemented.).

So ,individual Loan classes are.

public class HouseLoan extends Loan{    
    public void checkBankSolvency() {
        System.out.println("Checking Bank Solvency for house Loan");        
    }
    public void checkPeoperty() {
        System.out.println("Checking Property for house Loan");
    }
    public void checkAllAccountStatement(){}
    public void checkBusiness() {}
    public void checkEmployment() {}
    public boolean needCheckEmployment(){return false;}
    public boolean needCheckBusiness(){return false;}
    public boolean needCheckAllAccountStatement(){return false;}
}

We have here only Property and Solvency Checking.

public class StudyLoan extends Loan{
    public void checkBankSolvency() {
        System.out.println("Checking Bank Solvency for Student Loan");
    }    
    public void checkBusiness() {}    
    public void checkEmployment() {}    
    public void checkPeoperty() {}
    public void checkAllAccountStatement() {}
    public boolean needCheckProperty(){return false;}
    public boolean needCheckAllAccountStatement(){return false;}
    public boolean needCheckEmployment(){return false;}
    public boolean needCheckBusiness(){return false;}
}

We have here only Solvency Checking.

public class ConsumerLoan extends Loan{
    public void checkAllAccountStatement() {
        System.out.println("Checking all bank account statement for Consumer Loan");       
    }
    public void checkBusiness() {
        System.out.println("Checking Business for Consumer Loan");
    }
    public void checkEmployment() {
        System.out.println("Checking Employment for Consumer Loan");
    }
    public void checkPeoperty() {}
    public void checkBankSolvency() {    }
    public boolean needCheckProperty(){return false;}
    public boolean needCheckBankSolvency(){return false;}
}

We have here Business, Employment, All Account Statement Checking.

Now, a client(contains main). It will call appropriate loan sanction process.

public class Program {
    public static void main(String[] args) {
        HouseLoan homeLoan = new HouseLoan();
        StudyLoan studentLoan = new StudyLoan();
        ConsumerLoan televisionLoan = new ConsumerLoan();
        System.out.println("Providing a Home Loan has been started");
        homeLoan.provideLoan();
        System.out.println("\nProviding a Student Loan has been started");
        studentLoan.provideLoan();
        System.out.println("\nProviding a Consumer Loan has been started");
        televisionLoan.provideLoan();
    }
}

Java Example :

When we are keeping the method blank for not implemented method.

C# Example :

  1. Method name and implementation change due to dot net works little differently.
  2. New keyword used for overriding super class implemented method.

Usages :

  • To implement the invariant (not changeable) part of an algorithm once and leave it rest for sub classes to implement.
  • When we need an abstract base class containing common code and sub classes implement on changed implementation code. So, it is very helpful for refactoring.