Understanding the Template Method Design Pattern

Chidume Nnamdi 🔥💻🎵🎮
Bits and Pieces
Published in
6 min readDec 26, 2018

--

Image form pexels.com

In our last article in the series, we discussed in-depth〽 about the Strategy Method. In this article📄, we will look at the Template Method. One of the many design patterns that help developers write📝 well-structured apps.

Tip: Build software faster as a team with Bit. It helps your team easily share components and use them together like Lego to build new things. Give it a try.

💡 Basic Idea

Template Method is a behavioral design pattern that lets one define an “invariant” steps or program flow in an algorithm. Invariant means cannot be changed, it is the same(like defining a const wink😉). The subclasses of the template can redefine the behavior of the algorithm.

The invariant steps🚶🚶 are implemented in an abstract base class. The abstract base class (1) consist of the abstract methods(2) where the subclasses can implement their behavior and a method(3) which defines the sequence(4) of how the invariant steps will be called.

(1)abstract class TEMPLATE_CLASS {
sequence() {
(4)a()
(4)b()
}
(2)abstract a()
(2)abstract b()
}

To understand this concept. Let’s say we have a recipe to produce Shawarma🍰:

bake bread🍞
|
v
vegetable fillings🍀
|
v
chili pepper
|
v
meat🍗
|
v
roll n wrap🍥
  1. Bake bread
  2. Add vegetable fillings
  3. Add chili pepper
  4. Add meat
  5. Roll the mixture in aluminum foil and heat it.
  6. Ready delicacy

Let’s represent this in TypeScript code:

class SharwamaRecipe {
this.sharwama = null
prodSharwama() {
add_bread()
bake_bread()
vegetable_fillings()
chilli_pepper()
meat()
roll_n_wrap()
}
add_bread() {
log('Add Bread')
}
bake_bread() {
log('Bake bread')
}
vegetable_fillings() {
log('Add vegetable fillings')
}
chilli_pepper() {
log('Add chilli pepper')
}
meat() {
log('Add meat')
}
roll_n_wrap() {
log('Roll and Wrap')
}
}

The above is the recipe or algorithm(prodSharwama) to make a sharwama bread. If I order a sharwamma bread the steps will be followed to prepare it, but I might want a different kind of sharwama. I might want a chicken🐔 as the meat🍗, so the following steps are followed:

  1. Bake bread
  2. Add vegetable fillings
  3. Add chili pepper
  4. Add chicken🐓🍖
  5. Roll the mixture in aluminum foil and heat it.
  6. Ready delicacy🍰
class ChickenSharwamaRecipe extends SharwamaRecipe {
meat() {
log('Add chicken')
}
}

See the same steps is followed but the only thing is that we added chicken instead of meat. But the recipe was followed. So, in the end, we have a Chicken sharwama.

I might want a different kind of bread, either pita or flour tortilla wraps. If we choose a pita bread, it will go like this:

  1. Bake pita bread
  2. Add vegetable fillings
  3. Add chili pepper
  4. Add chicken
  5. Roll the mixture in aluminum foil and heat it.
  6. Ready delicacy
class ChickenPitaSharwamaRecipe extends SharwamaRecipe {
meat() {
log('chicken')
}
add_bread() {
log('pita')
}
}

Tortilla wraps will be this:

  1. Bake Tortilla wraps
  2. Add vegetable fillings
  3. Add chili pepper
  4. Add chicken
  5. Roll the mixture in aluminum foil and heat it.
  6. Ready delicacy
class ChickenTortillaSharwamaRecipe extends SharwamaRecipe {
meat() {
log('chicken')
}
add_bread() {
log('TortillaWraps')
}
}

For the meat, we might want to choose from a variety: pork🐗, steak or beef🐄 or mutton🐑.

class PorkSharwamaRecipe extends SharwamaRecipe {
meat() {
log('pork')
}
}
class SteakSharwamaRecipe extends SharwamaRecipe {
meat() {
log('steak')
}
}
class BeefSharwamaRecipe extends SharwamaRecipe {
meat() {
log('beef')
}
}

If I am a vegetarian, I would skip the Add chicken step but the recipe/algorithm remains the same.

class VegSharwamaRecipe extends SharwamaRecipe {
meat() {}
}

We have used a yummy snack analogy to explain the Template Method. The SharwamaRecipe class is the parent class that defines how to produce a sharwama snack. The prodSharwama method is the method that implements the steps required to produce a sharwama snack.

We call the prodSharwama method a template method. The template method defines the steps or algorithm that subclasses would follow to produce different types of sharwama.

The template method defines an algorithm(steps) and fixes their ordering. By defining those steps, it lets its subclasses to vary those steps to suit their needs. The SharwaRecipe class defined the steps:

prodSharwama() {
1. add_bread()
2. bake_bread()
3. vegetable_fillings()
4. chilli_pepper()
5. meat()
6. roll_n_wrap()
}

and fixed their ordering: add bread, bake it, add veg. fillings and chili, next add meat and roll n’ wrap.

The ChickenSharwamaRecipe varied the 5. step to add a chicken to produce a chicken sharwama.

🗽Structure

The ABSTRACT CLASS defines runAlgorithm, step1, step2, step3 methods. The runAlgorithm method calls step1, step2, and step3.

abstract class ABSTRACT_CLASS {
runAlgorithm() {
this.step1()
this.step2()
this.step3()
}
abstract step1(): void;
abstract step2(): void;
abstract step3(): void;
}

The runAlgorithm implements the series of calls which the algorithm will take: first the step1 method is called, followed by step2 and lastly, step3. It's up to the designer to state the steps an algorithm will take, then allow the client to modify the behavior of the steps but the client cannot change the algorithm's call sequence.

In our ABSTRACT_CLASS class the runAlgorithm is the algorithm provided by the class, the client can't modify this method, if they would they must call back to the base method. The step* methods are to be modified by the client to specific to provide a specific behavior.

class MyBehaviour extends ABSTRACT_CLASS {
runAlgorithm() {
log("My run algorithm")
super.runAlgorithm()
}
step1() {
log("My step 1")
}
step2() {
log("My step 2")
}
step3() {
log("My step 3")
}
}
function run (arg: ABSTRACT_CLASS) {
arg.runAlgorithm()
}
run(new MyBehaviour())// logs:
// My run algorithm
// My step 1
// My step 2
// My step 3

You see, the MyBehaviour class overrides the step* methods and implements its own behavior. Notice it overrode the runAlgorithm which defines the algorithm steps and called back to the parent base method. If it didn't call back to the base method, the algorithm's structure would be altered and template method rule would be broken.

🔚Conclusion

The Template Method and the Strategy Pattern are quite similar. Template method varies the steps within an algorithm but the Strategy Pattern varies the entire algorithm.

Remember, you don’t have to implement a design pattern as described. You have to thoroughly understand it and know when to apply it. And if you don’t understand it, no worry, keep referring to it again and again for insights. With time you’ll get the hang of it, and in the end, you will see the benefits.

Next, in our series, we will be looking into the Interpreter Design Pattern.

If you have any question❓ regarding this or anything I should add, correct📝 or remove✖, feel free to comment💬 and ask me antyhing! Thanks 👏

💞Credits

--

--

JS | Blockchain dev | Author of “Understanding JavaScript” and “Array Methods in JavaScript” - https://app.gumroad.com/chidumennamdi 📕