4 Common Use of Template Design pattern: - Design Pattern Series

Introduction 

In this article we will try to understand 4 important uses of template design patterns. Template design pattern is one of those patterns which are used unknowingly or knowingly in many places. This article will flesh out 4 places where this pattern is seen evident.

Let's start first with definition and then rest will follow.

Definition :- Template pattern is  used in scenarios where we want to create  extendable behaviors in generalization and specialization relationship.

Introduction to template pattern

Template pattern belongs to behavioral pattern category. Template pattern defines a main process template and this main process template calls sub-processes in a sequential manner.  Later the sub processes of the main process can be altered to generate a different behavior. 

For example below is a simple process to parse data and load the same in to oracle. The overall general process has 3 fixed steps:- 

  • Load data from the source

  • Parse the data

  • Dump the same in to oracle

a1.jpg
 

Figure: - General process

Now you can alter "Load" and "Parse" implementation to create a CSV file load process. The overall sequence of calling "Load", "Parse" and "Dump" will remain same but we have the full liberty to change the implementation of "Load" , "Parse" and "Dump" thus creating a new process. 

a2.jpg
 

Figure: - Template thought process

You can see from the above figure how we have altered 'Load' and 'Parse' sub process to generate CSV file and SQL Server load process. The 'Dump' function and the sequence of how the sub processes are called are not altered in the child processes.

In order to implement template pattern we need to follow 4 important steps:

  1. Create the template or the main process by creating a parent abstract class.

  2. Create the sub processes by defining abstract methods and functions.

  3. Create one method which defines the sequence of how the sub process methods will be called. This method should be defined as a normal method so that we child methods cannot override the same.

  4. Finally create the child classes who can go and alter the abstract methods or sub process to define new implementation.

public abstract class GeneralParser
{
    protected abstract void Load();

    protected abstract void Parse();
    protected virtual void Dump()
    {
        Console.WriteLine("Dump data in to oracle");
    }
    public void Process()
    {
        Load();
        Parse();

        Dump();
    }
 
}

The 'SqlServerParser' inherits from 'GeneralParser' and overrides the 'Load' and 'Parse'  with SQL server implementation.

public class SqlServerParser : GeneralParser
{
    protected override void Load()
    {
        Console.WriteLine("Connect to SQL Server");
    }
    protected override void Parse()
    {
        Console.WriteLine("Loop through the dataset");
    }

}

The 'FileParser' inherits from General parser and overrides the 'Load' and 'Parse' methods with file specific implementation.

public class FileParser : GeneralParser
{
    protected override void Load()
    {
        Console.WriteLine("Load the data from the file");
    }
    protected override void Parse()
    {
        Console.WriteLine("Parse the file data");
    }
 
}

From the client you can now call both the parsers.

FileParser ObjFileParser = new FileParser();
ObjFileParser.Process();
Console.WriteLine("-----------------------");
SqlServerParser ObjSqlParser = new SqlServerParser();
ObjSqlParser.Process();
Console.Read();

The outputs of both the parsers are shown below.

Load the data from the file
Parse the file data
Dump data in to oracle
-----------------------
Connect to SQL Server
Loop through the dataset
Dump data in to oracle

Now let's walk through some practical scenarios where "Template" pattern can be implemented.

Scenario 1:- Flexible extendable generalized specialized user interfaces.

Many times we come across UI which have all the things almost same but with some small difference in look and feel. For instance in the below screen the data is all same but the one screen has the back ground color different than other.

a3.jpg
 

                                                                        Figure:

In this scenario in the form constructor will become the main process which will call three processes / functions:-

  • InitializeComponent :- This will create the UI objects need for the form.

  • LoadCustomer :- This function will load data and bind to the grid.

  • LoadGrid :- This function will define the look and feel of the grid.

public Form1()
{
    InitializeComponent();
    LoadCustomer();
    LoadGrid();
}


Below is the full code of the base form. Please note the "LoadGrid" is an abstract method. In other words we can create forms with different color implementation without disturbing the rest of the part of the form.

public abstract partial class Form1 : Form
{
    protected Customers objCustomers = new Customers();
    protected List<Customer> oCustomerList;
    public Form1()
    {
        InitializeComponent();
        LoadCustomer();
        LoadGrid();
    }

    public void LoadCustomer()
    {
        oCustomerList = objCustomers.GetCustomers();
    }
    public abstract void LoadGrid();

}

In other words if you want to create a new form with different color back ground you can keep the other code as it is and just override the "LoadGrid" functionality with a different color / look and feel , below is the sample code for the same.

public partial class Form3 : Form1
{
      ....
      ....
      ....
      ....
        public override void LoadGrid()
        {
            dgGridCustomer.DataSource = oCustomerList;
            dgGridCustomer.BackgroundColor = Color.Aqua;
            dgGridCustomer.ForeColor = Color.Brown;
        }
}

Scenario 2:- ASP.NET page life cycle

One very but obvious scenario where we see template pattern very much visible is in ASP.NET page life cycle. In ASP.NET page life cycle the page life cycle sequence is fixed but it provides full authority to override implementation for the each of those sequences.

For instance in ASP.NET page life cycle we have various events with sequence like Init, Load , Validate , Prerender , render etc. Now the sequence is fixed we cannot change them, but yes we can override the implementation for each of these events as per our need.

 

a4.jpg
 

 

                                                                                                          Figure:

Scenario 3:- XML Parser

The other scenario which is applicable for template pattern is the XML parser.  In XML we normally parse the parent and the child elements. In many scenarios the parsing is almost common with minor child element changes.

For instance in the below code snippet we have Customer as the parent element and every customer will have orders and orders will products.

Now the parsing of Customer and Order elements will be same but the products tag can have size property depending on situation.

For instance in the below code snippet the product element has only name of the product and amount. 

<Customer Name="Shiv">
<Orders OrderNumber="1001">
<Product Name="Shirts" Amount="1000"/>
<Product Name="Socks" Amount="100"/>
</Orders>
</Customer>

There can be situations where your product element can have other variations as shown in the below XML snippet.  In this case you can just override the parsing process of product element and keep the overall XML parsing process sequence same.

<Customer Name="Shiv">
<Orders OrderNumber="1001">
<Product Name="Shirts" Amount="1000">
<LargeSize/>
</Product>
<Product Name="Socks" Amount="1000">
<SmallSize/>
</Product>
</Orders>
</Customer>


Scenario 4:- Validation in business components.

Business classes have validation and we would like to create different versions of business classes with different validation logic. You can see in the below code we have a base supplier class. The set of the supplier code property is first calling "validatesuppcode" function and then setting the value.

This "validatesuppcode" function is defined as virtual and can be overridden by other classes to create different validation logic.

 public class Supplier
{
    private string _SupplierCode;

    public string SupplierCode
    {
        get
        {
            return _SupplierCode;
        }
        set
        {
            ValidateSuppCode(value);
            _SupplierCode = value;
        }
    }

    public virtual void ValidateSuppCode(string SuppCode)
    {
        if (SuppCode.Length == 0)
        {
            throw new Exception("Can not be null");
        }
    }
}

We can now inherit the main base supplier class and create a new supplier class called as "SupplierNew" which checks for length greater than 10 also.

public class SupplierNew : Supplier
{
    public override void ValidateSuppCode(string SuppCode)
    {
        base.ValidateSuppCode(SuppCode);
        if (SuppCode.Length > 10)
        {
            throw new Exception("can not be more than 10");
        }
    }
}

Feel free to download these FAQ PDF's, articles of design patterns from my site and also I have collected around 400 FAQ questions and answers in SilverLight, Azure, VSTS, WCF, WPF, WWF, SharePoint, design patterns, UML etc.

 


Similar Articles