Template Pattern

Template Pattern is the behavioural pattern.

Motive: The Template Method defines the steps of an algorithm and allows sub class to provide the implementation for one or more steps. Template Method let subclass redefine certain steps of an algorithm without changing the algorithm’s structure.

Where To Use

  1. Want to have control over algorithm to avoid duplicate code.
  2. Use Template if you are aware of requirement complexity/algorithm. This is for code reuse and allow subclass to specify behavior.

Real World Example:

  • Servlet  (explained after case study)
  • Java – Arrays sort, mergeSort (Refer Head First Book)
  • JFrame – update() (Refer Head First Book)
  • HibernateCallback used in HibernateTemplate’s execute(..) methods (Refer Spring Blogs)
  • Struts – RequestProcessor

Case Study

Develop application for processing flat file for a) Stock and b) Derivatives.

Requirement

  1. Stock support CSV format where as Derivative support txt
  2. Stock data is separated by delimiter “,” where as Derivative data within Flat file separated by “|”. Data is persisted within database.
  3. We can configure logging into system optionally.

Class Diagram: Please open class diagram in new window if problem occurs.

Template Pattern Class Diagram

Template Pattern Class Diagram

Explanation:

DataHandler provide template method to algorithm for processing financial system data files.

Algorithm: Template Method – execute()
1. Validate file type
2. Transform Data
3. Process Data

Subclass should implement specific behaviour based on investment file type
(Stock/Derivative).

Hook: Method – isDebugMode()
DataHandler define default configuration for setting log in debug mode. Subclass can override this method. Subclass can use hook to control execution of algorithm.

Code:

Template Class

package com.behavioral.template;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * DataHandler provide template method execute which define algorithm for
 * processing financial system data files. <br>
 *
 * Algorithm: <br>
 * 1. Validate file type <br>
 * 2. Transform Data <br>
 * 3. Process Data <br>
 *
 * Subclass should implement specific behaviour based on investment file type
 * (Stock/Derivative).
 *
 *
 * @author Shishir.Kumar
 */
public abstract class DataHandler {

 /**
  * This is template method define algorithm for ocessing financial system
  * data files.
  *
  * @param fileName String
  */
 public final void execute(String fileName){
  if(isValidFileType(fileName)){
   // process file
   try {
    // Open the file that is the first
    FileInputStream fstream = new FileInputStream(fileName);
    // Get the object of DataInputStream
    DataInputStream in = new DataInputStream(fstream);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
    String strLine;
    // Read File Line By Line
    while ((strLine = br.readLine()) != null) {
     if(isDebugMode()){
      System.out.println(“Processing data:” + strLine);
     }
     DataObject data = transformData(strLine);
     process(data);
    }
    // Close the input stream
    in.close();
   } catch (Exception e) {// Catch exception if any
    System.err.println(“Error: ” + e.getMessage());
   }
  }
 }

 /**
  * Validate File type. Subclass should implent specific
  * behaviour.
  *
  * @param fileName String
  * @return boolean
  */
 protected abstract boolean isValidFileType(String fileName);

 /**
  * Transform data to data Object. Subclass should implent specific
  * behaviour.
  *
  * @param fileName String
  * @return DataObject
  */
 protected abstract DataObject transformData(String fileName);

 /**
  * Subclass should override this method to persist/process data within
  * database.
  *
  * @param data DataObject
  */
 protected abstract void process(DataObject data);
 
 /**
  * This is a hook method and DataHandler define default configuration for
  * setting log in debug mode. Subclass can override this method. Subclass
  * can use hook to control execution of algorithm.
  *
  * @return boolean
  */
 protected boolean isDebugMode(){
  return false;
 }
}

Template SubClass – For Stock and Derivative

package com.behavioral.template;

import java.math.BigDecimal;
import java.util.StringTokenizer;

public class StockHandler extends DataHandler {

 @Override
 protected boolean isValidFileType(String fileName) {
  // Support processing of file if in CSV format
  return fileName.endsWith(“.csv”);
 }

 @Override
 protected void process(DataObject data) {
  if(isDebugMode()){
   log(“Persisting Data!!!”);
  }
  // Persist information
  StockDataObject dataVal = (StockDataObject)data;
  log(“Stock Name:” + dataVal.getName());
  log(“High Value:” + dataVal.getHighValue().toString());
  log(“Low Value:” + dataVal.getLowValue().toString());
  log(“Open Value:” + dataVal.getOpenValue().toString());
  log(“Close Value:” + dataVal.getCloseValue().toString());
 }

 @Override
 protected DataObject transformData(String strLine) {
  if(isDebugMode()){
   log(“\nStarted Transformation!!!”);
  }
  StringTokenizer tokenizer = new StringTokenizer(strLine,”,”);
  StockDataObject dataObject = null;
  if(tokenizer.hasMoreTokens() && tokenizer.countTokens()==5){
   dataObject = new StockDataObject();
   dataObject.setName(tokenizer.nextToken());
   dataObject.setOpenValue(new BigDecimal(tokenizer.nextToken()));
   dataObject.setHighValue(new BigDecimal(tokenizer.nextToken()));
   dataObject.setLowValue(new BigDecimal(tokenizer.nextToken()));
   dataObject.setCloseValue(new BigDecimal(tokenizer.nextToken()));
  }
  if(isDebugMode()){
   log(“Transform Successful!!!”);
  }
  return dataObject;
 }

 private void log(String str){
  System.out.println(str);
 }
 
 @Override
 protected boolean isDebugMode() {
  return true;
 }
}

package com.behavioral.template;

public class DerivativeHandler extends DataHandler {

 @Override
 protected boolean isValidFileType(String fileName) {
  // Support processing of file if in txt format
  return fileName.endsWith(“.txt”); }

 @Override
 protected void process(DataObject data) {
  System.out.println(“Process data for derivative!!!”);
 }

 @Override
 protected DataObject transformData(String fileName) {
  System.out.println(“Transforming data for derivative!!!”);
  return null;
 }

}

Reference DataObject Class

package com.behavioral.template;

import java.io.Serializable;

/**
 * DataObject Interface.
 * @author Shishir Kumar
 */
public interface DataObject extends Serializable {

}

package com.behavioral.template;

import java.math.BigDecimal;

/**
 * Data Object for Stock.
 *
 * @author Shishir Kumar
 */
public class StockDataObject implements DataObject {

 private static final long serialVersionUID = 1L;
 private String name;
 private BigDecimal openValue;
 private BigDecimal highValue;
 private BigDecimal lowValue;
 private BigDecimal closeValue;
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public BigDecimal getOpenValue() {
  return openValue;
 }
 public void setOpenValue(BigDecimal openValue) {
  this.openValue = openValue;
 }
 public BigDecimal getHighValue() {
  return highValue;
 }
 public void setHighValue(BigDecimal highValue) {
  this.highValue = highValue;
 }
 public BigDecimal getCloseValue() {
  return closeValue;
 }
 public void setCloseValue(BigDecimal closeValue) {
  this.closeValue = closeValue;
 }
 public BigDecimal getLowValue() {
  return lowValue;
 }
 public void setLowValue(BigDecimal lowValue) {
  this.lowValue = lowValue;
 }
}

Client Class:

package com.behavioral.template;

/**
 * Sample client to test Template Pattern.
 * @author Shishir Kumar
 */
public class TemplateClient {
 public static void main(String[] args) {
  DataHandler handler = new StockHandler();
  handler.execute(“Share.csv”);
 }
}

Sample File: Share.csv

Download this file and save as “Share.csv” within classpath.

Real World Example: Servlet

  • Servlet Life Cycle
    init()
    service()
    destroy()
  • Service method is an abstract method in GenericServlet Class.
  • HttpServlet extends GenericServlet and implement service method.
  • Based on HTTP request type, HTTPServlet invokes
    – doGet, doPost, doHead, doPut, doDelete, doTrace, doOptions
  • Developers extend HttpServlet and write meaningful method – doGet, doPost
  • Template – HttpServlet service method define template for handling HTTP requests.

Intresting Fact: Template Method follow

Hollywood Principle“Don’t call me, I will call you“
Enforces “Open Closed principle” – A class should be open for extension, but closed for modification.

Should Read: Strategy Pattern

Download Code: TemplatePattern.zip

Please share your feedback/query.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: