The Template Method Pattern and Usage in Unity

Posted by : on

Category : C#   Unity

What is the template method pattern

The template method pattern is used to define a series of operations in an algorithm, that some of those don’t have specific implementation, but the implementation is dependant on the type that uses them.

Let’s suppose for example that we have an enemy object that we want it to go and attack the player. The enemy will move, attack the player either in melee or from distance depending on its type, maybe say something to the player and then run away.

With the template method this will look something like this:

public abstract class Enemy
{
   public void PerformAttack()
   {
      ApproachPlayer();
      AttackPlayer();
      SaySomething();
      RunAway();
   }

   private void ApproachPlayer()
   {
      Console.WriteLine("Approaching the player");
   }
   
   protected abstract void AttackPlayer();

   protected virtual void SaySomething()
   { }
   
   private void RunAway()
   {
      Console.WriteLine("Running away");
   }
}

public class Goblin : Enemy
{
   protected override void AttackPlayer()
   {
      Console.WriteLine("Attacking in melee");
   }

   protected override void SaySomething()
   {
      Console.WriteLine("DIE human!");
   }
}

public class Archer : Enemy
{
   protected override void AttackPlayer()
   {
      Console.WriteLine("Attacking from distance");
   }
}

Then the following code:

Enemy goblin = new Goblin();
Enemy archer = new Archer();

goblin.PerformAttack();
Console.WriteLine();
archer.PerformAttack();

will have the output:

Approaching the player
Attacking in melee
DIE human!
Running away

Approaching the player
Attacking from distance
Running away

With the template method, the behaviour of our enemies will change in some parts of the algorithm. The common functionality will be in one place, but the functionality that differs will be encapsulated in each class.

Whenever we want to change the behavior of one of our enemies, we only have to change the relevant class without fear of breaking something in the other classes.

The Hollywood principle

The above code is also known as an example of the Hollywood principle, or “don’t call us, we’ll call you” because the child class doesn’t call the base abstract class to perform some functionality, but the opposite happens. The PerformAttack() method is part of the base class and is that method that will call the specific implementation of each child.

Other than the abstract PerformAttack() method, in the template pattern, there are two more ways to call functionality from the child class.

Hooks

The first are the Hooks. In the previous example, the virtual SaySomething() method is empty. If it is overridden by the child class will execute its statements otherwise will do nothing.

Hooks are useful when our algorithm has parts that may be needed sometimes but not always.

Virtual methods

The second are classic virtual methods. For example we could have written the previous code like this:

public abstract class Enemy
{
   public void PerformAttack()
   {
      ApproachPlayer();
      AttackPlayer();
      RunAway();
   }

   private void ApproachPlayer()
   {
      Console.WriteLine("Approaching the player");
   }

   protected virtual void AttackPlayer()
   {
      Console.WriteLine("DIE human!");
   }

   private void RunAway()
   {
      Console.WriteLine("Running away");
   }
}

public class Goblin : Enemy
{
   protected override void AttackPlayer()
   {
      base.AttackPlayer();
      Console.WriteLine("Attacking in melee");
   }
}

public class Archer : Enemy
{
   protected override void AttackPlayer()
   {
      Console.WriteLine("Attacking from distance");
      base.AttackPlayer();
   }
}

Then the output would be:

Approaching the player
DIE human!
Attacking in melee
Running away

Approaching the player
Attacking from distance
DIE human!
Running away

But i don’t like this approach. Calling the base method, can lead to confusion when and if we should call it.

A different approach, if we wanted to have the ability to perform some operation either before or/and after, like for example to have the option our enemy to say something before or/and after the attack will be to provide two Hooks one SaySomethingBeforeAttack() and one SaySomethingAfterAttack() and have the implementation override whichever is necessary.

Conditional execution

With the template method, conditional execution is an option that we can add to the base class. For example:

public abstract class Enemy
{
   public void PerformAttack()
   {
      ApproachPlayer();

      if (DistanceToPlayer < 10)
      {
         MeleeAttack();
      }
      else
      {
         RangedAttack();
      }
      
      SaySomething();
      RunAway();
   }

   protected abstract void MeleeAttack();
   protected abstract void RangedAttack();

   private void ApproachPlayer()
   {
      Console.WriteLine("Approaching the player");
   }
   
   protected abstract void AttackPlayer();

   protected virtual void SaySomething()
   { }
   
   private void RunAway()
   {
      Console.WriteLine("Running away");
   }
}

Here the MeleeAttack() and RangedAttack() methods are abstract, but they could also be empty virtual hooks, if we don’t want all our enemies to have both types of attack.

The template method pattern in Unity

In Unity, creating base abstract classes, sometimes is undesirable because many programmers who have learned coding in Unity are not experienced in inheritance. That means that if someone is going to use our code, may forget to call the base method or call it in the wrong place.

Sometimes though, inheritance makes more sense to be used instead of composition and then we have a dilemma if our code is going to be used by other people: Should we implement a base abstract class or bugs are gonna happen because of the missing calls to the base class’ methods ?

The template pattern offers a solution to that problem, by ensuring that either a method has to be implemented as it will be abstract, because the program won’t compile otherwise, or by making hooks that make the call to the base method redundant.

Usage to avoid calling the base class

Here is a generic example.

Instead of writing our code like this:

public abstract class Example
{
   public virtual void DoSomething()
   {
      Console.WriteLine("Doing common functionality");
   }
}

public class ConcreteExample : Example
{
   public override void DoSomething()
   {
      base.DoSomething();
      Console.WriteLine("Specific functionality");
   }
}

By using the template method we can have the equivalent code:

public abstract class Example
{
   public void DoSomething()
   {
      Console.WriteLine("Doing common functionality");
      SpecificImplementation();
   }

   protected abstract void SpecificImplementation();
}

public class ConcreteExample : Example
{
   protected override void SpecificImplementation()
   {
      Console.WriteLine("Specific functionality");
   }
}

Hooks can also be used for situations where an implementation isn’t needed for every child class.

The template method can’t cover situations where we want to replace functionality of a virtual class. But in those cases there is a good chance that we will violate the Liskov substitution principle and besides that, in those situations a solution with composition, like using the Strategy pattern is probably more appropriate than inheritance.

Conclusion

With the template method, we always have to keep in mind, that we don’t violate the Liskov substitution principle. This isn’t only true for overriding the virtual methods, but also for our hooks.

Also, we have to be careful with our method’s access modifiers so that the template method cannot be overridden and the required methods are abstract.

Good naming conventions for our methods, make our intend more clear, so using the prefixes “pre” and “post” like PreAttack() and PostAttack() is a good idea.

Finally it is a good idea to keep the methods that have to be overridden to a minimum. The more methods that the children of our base class have to override, the more rigid our code becomes. If we find ourselves in a situation where we have many such methods, then breaking our class to smaller classes and connecting those classes to our base via composition may be preferable.

That’s it for the template method pattern. I hope you found this post useful. Thank you for reading and as always, if you have any questions or comments you can use the comments section or contact me directly via the contact form or by email. Also if you don’t want to miss any of the new blog posts, you can always subscribe to my newsletter or the RSS feed.


About Giannis Akritidis

Hi, I am Giannis Akritidis. Programmer and Unity developer.

Follow @meredoth
Follow me: