Home > Extreme Programming, Refactoring, Software Development > The Template Pattern A Benevolent Dictator

The Template Pattern A Benevolent Dictator

Ben Yoder the Template Pattern

July 22nd 2009 | Ben Yoder

The Template Pattern: A Benevolent Dictator

The Template Pattern is unique because of the level of control maintained at the top level. An abstract class controls the steps and the possible default implementations of the algorithm, but it’s kind enough to let its subclasses modify the behavior in pre-defined methods.

Similar design patterns, and specifically the Strategy pattern, prescribe the encapsulation of individual algorithms and logic into single classes that can be called independently.

The Template Pattern is useful for avoiding code duplication and keeping code maintainable. When you copy and paste the same—or very similar—logic across code you should encapsulate that code to prevent drift. This is when a benevolent dictator class helps clean up your code.

Drift may occur due to a change in requirements. Imagine you are working on an application that has a requirement to create an audit record whenever a user edits information on a form. During version 1.0, you created an AuditLogger class that simply writes a record to the database.

public class AuditLogger
{
    public void InsertAuditRecord(){...}
}

However, for version 2.0 you have this requirement: whenever a regular user edits information on certain forms, an email should be sent to a system admin. Additionally system admins, due to their higher level of access, require separate security audit records to be created elsewhere. As quick fix, you could add methods called EmailNotification() and InsertAdminAuditRecord() to AuditLogger which can be called from the Save() method on the forms depending on the user type.

But after that’s been wrapped up, requirements change and a new power user type has been added to the system. This user type requires a single audit record, but this time there is no need to send an email notifying administrators. You could create a mess on all your forms by adding methods to AuditLogger and making decisions on the form, or you could encapsulate what differs between the auditing logic per user-type, recognizing that requirements may change again.

In this case, AuditLogger currently looks like:

public class AuditLogger
{
    public void InsertAuditRecord(){...}
    public void InsertAdminAuditRecord(){...}
    public void EmailNotification(){...}
}

In refactoring this to a Template Pattern, you’ll notice that InsertAuditRecord() and InsertAdminAuditRecord() are essentially the same logical step. By default, users should write a standard audit record, but administrators should write a special audit record. So in creating your Template class, you should define just a single virtual InsertAuditRecord() method that inserts a standard record and a virtual Notify() method that sends emails by default.

public abstract class AuditLogger
{
    public void Audit()
    {
        InsertAuditRecord();
        Notify();
    }

    public virtual void InsertAuditRecord()
    {
        Console.WriteLine("Auditing User...");
    }

    public virtual void Notify()
    {
        Console.WriteLine("Emailing Admin...");
    }
}

Next, create concrete implementations to define specific implementations of the methods, where needed. Your standard AuditLogger will simply be a concrete that extends AuditLogger with the default implementations, but your Admin and PowerUser loggers will override separate methods.

public class StandardAuditLogger : AuditLogger
{
}

public class AdminAuditLogger : AuditLogger
{
    public override void InsertAuditRecord()
    {
        Console.WriteLine("Auditing Admin User...");
    }

    public override void Notify()
    {
        return;
    }
}

public class PowerUserAuditLogger : AuditLogger
{
    public override void Notify()
    {
        return;
    }
}

The advantage of this is as requirements change, your specific logic is encapsulated, but you can continue to define default implementations. So if everyone except admins needs to send email notifications, you could pull the Notify() override out of the PowerUserAuditLogger and be done. And if another step was to be added to the audit process, a default method could be defined and called in the template without having to touch anything else.

The Template pattern becomes less useful the more the algorithms diverge. If you find yourself overriding every single method of the abstract Template class and adding in a lot of hook methods to control the flow from the subclasses, then the Template Pattern may not be your best choice. But if it looks like your code could use some iron fisted governing, let the Template call all the shots—and see how much simpler maintenance becomes.

Ben Yoder is a Senior .NET Consultant at Thycotic Software, an agile software consulting and product development company based in Washington DC. Secret Server is our flagship password management software product.

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: