Template method pattern


Sometimes I write a class that has many similar methods. All those methods start from initialization block, then there is a processing part and at the end there is finalizing segment. In other words those methods are only different in processing code – rest is the same.

When I see that kind of class I immediately start thinking about using template method patter. You can read about this pattern here . The general idea is that you have an abstract class that creates template method for concrete classes that derive from it and add its own functionality to this method.

I will show it by examples.

First let’s assume we have to write a class that will process a text file. The file contains only one line with an integer number. Our task is to write a methods that will increment (n ), decrement (n–) or multiple by two (n=*2) this number.

Let’s start from trivial implementation:

public class IntegerFileOperation
{
    private string filePath;

    public IntegerFileOperation(string filePath)
    {
        this.filePath = filePath;
    }

    public int Increment()
    {
        string numerText = File.ReadAllText(filePath);

        int integer;
        if (int.TryParse(numerText, out integer))
        {
            integer  ;

            File.WriteAllText(filePath, integer.ToString());

            return integer;
        }

        throw new InvalidOperationException();
    }

    public int Decrement()
    {
        string numerText = File.ReadAllText(filePath);

        int integer;
        if (int.TryParse(numerText, out integer))
        {
            integer--;

            File.WriteAllText(filePath, integer.ToString());

            return integer;
        }

        throw new InvalidOperationException();
    }

    public int MultipleByTwo()
    {
        string numerText = File.ReadAllText(filePath);

        int integer;
        if (int.TryParse(numerText, out integer))
        {
            integer *= 2;

            File.WriteAllText(filePath, integer.ToString());

            return integer;
        }

        throw new InvalidOperationException();
    }
}

As we can see our  class has three methods: Increment(), Decrement() and MultipleByTwo() – the only difference between them is in line where we change integer variable, rest is the same. There is lots of redundant code that should be removed, to do it we can introduce a base, abstract class.

public abstract class IntegerFileOperationBase
{
    private string filePath;

    protected abstract int DoOperation(int number);

    public IntegerFileOperationBase(string filePath)
    {
        this.filePath = filePath;
    }

    public int ChangeNumber()
    {
        string numerText = File.ReadAllText(filePath);

        int integer;
        if (int.TryParse(numerText, out integer))
        {
            integer = DoOperation(integer);

            File.WriteAllText(filePath, integer.ToString());

            return integer;
        }

        throw new InvalidOperationException();
    }
}

In IntegerFileOperationBase class we have a method ChangeNumber() which is a template method. This method opens a text file, reads its content, parses it as an integer and then invokes DoOperation method to change the integer variable. After all the new value is saved to the file. By various implementation of DoOperation method we can change the way that ChangeNumber method works. Here’s how we can do it:

public class IncrementIntegerInFile : IntegerFileOperationBase
{
    public IncrementIntegerInFile(string filePath)
        : base(filePath)
    {
    }

    protected override int DoOperation(int number)
    {
        return   number;
    }
}

public class DecrementIntegerInFile : IntegerFileOperationBase
{
    public DecrementIntegerInFile(string filePath)
        : base(filePath)
    {
    }

    protected override int DoOperation(int number)
    {
        return --number;
    }
}

public class MultipleByTwoIntegerInFile : IntegerFileOperationBase
{
    public MultipleByTwoIntegerInFile(string filePath)
        : base(filePath)
    {
    }

    protected override int DoOperation(int number)
    {
        return number * 2;
    }
}

The result of our  refactoring is a code without redundancy. I don’t like this solution, because I feel it’s too complicated for such an easy task (we have four classes instead of one). We can solve this problem by reimplementing it with delegate mechanism. Instead of an abstract  DoOperation() method we can use a delegate that will be passed to the ChangeNumber() method as a parameter (I use generic Func<int, int> delegate as a type – read more. To implement Increment(), Decrement() and MultipleByTwo() methods we use ChangeNumber method with lambda expression as a parameter:

public class IntegerFileOperationWithDelegate
{
    private string filePath;

    public IntegerFileOperationWithDelegate(string filePath)
    {
        this.filePath = filePath;
    }

    public int ChangeNumber(Func doOperation)
    {
        string numerText = File.ReadAllText(filePath);

        int integer;
        if (int.TryParse(numerText, out integer))
        {
            integer = doOperation(integer);

            File.WriteAllText(filePath, integer.ToString());

            return integer;
        }

        throw new InvalidOperationException();
    }

    public int Increment()
    {
        return ChangeNumber(n =>   n);
    }

    public int Decrement()
    {
        return ChangeNumber(n => --n);
    }

    public int MultipleByTwo()
    {
        return ChangeNumber(n => n * 2);
    }
}

This makes that we have only one, clean class without redundant code. If I need to write a class with lots of repeated code I try to use this pattern to solve it.

Do you like that kind of solution? Or maybe it’s completely wrong? Please tell me in the comments.


You may also like

Lesser known Clojure: variants of threading macro

ClojureScript: JavaScript Interop

Defining Node.js task for Heroku Scheduler