Introduction to Template Method Pattern
The Template Method is a behavioral design pattern that defines the skeleton of an algorithm in a base class but lets subclasses override specific steps of the algorithm without changing its structure. This pattern allows you to make parts of an algorithm optional, mandatory, or customizable by the subclasses.
Here's a breakdown of the notation:
- The arrow (
<|..
) signifies inheritance.ChocolateCake
andVanillaCake
are subclasses ofCakeRecipe
. - The
+
sign before a method indicates that the method is public. - The
#
sign before a method indicates that the method is protected. - The
-
sign before a method indicates that the method is private or abstract.
In this pattern, we create an abstract base class with a template method being the skeleton of an operation. This template method contains steps (often represented by methods), and these steps can be either abstract methods (must be implemented by subclasses) or hook methods (optional to be overridden by subclasses).
Classic Implementation Of The Template Method Pattern
In this example, the CakeRecipe
is the base class which provides the steps to
bake a cake. Two of the steps, mixIngredients()
and decorate()
, can be
overridden by subclasses. ChocolateCake
and VanillaCake
are the subclasses
that
provide their own implementation of mixIngredients()
, and ChocolateCake
overrides decorate()
. All cakes follow the same process, but specific steps
can
be customized based on the type of cake.
abstract class CakeRecipe {
public bakeCake(): void {
this.preheatOven();
this.mixIngredients();
this.bake();
this.coolingDown();
this.decorate();
}
protected preheatOven(): void {
console.log("Preheating the oven to 350 degrees F (175 degrees C).");
}
protected bake(): void {
console.log("Baking the cake...");
}
protected coolingDown(): void {
console.log("Cooling down the cake...");
}
protected abstract mixIngredients(): void;
protected decorate(): void {
console.log("Decorating the cake...");
}
}
class ChocolateCake extends CakeRecipe {
protected mixIngredients(): void {
console.log(
"Mixing ingredients for the chocolate cake: chocolate, sugar, butter, flour, eggs, cocoa powder."
);
}
// This cake requires special decoration
protected decorate(): void {
console.log("Adding chocolate icing for decoration.");
}
}
class VanillaCake extends CakeRecipe {
protected mixIngredients(): void {
console.log(
"Mixing ingredients for the vanilla cake: sugar, butter, flour, eggs, vanilla extract."
);
}
// This cake does not require special decoration,
// so we do not override the decorate method
}
function bake(cake: CakeRecipe): void {
cake.bakeCake();
}
console.log("Baking a Chocolate Cake:");
bake(new ChocolateCake());
console.log("Baking a Vanilla Cake:");
bake(new VanillaCake());
When To Use Template Method Pattern
Template Method pattern isn't always the best solution. Understanding when to use it is key to designing effective software. Here are a few code smells or indicators that the Template Method pattern could be a good fit:
Duplicate code in subclasses
This is perhaps the most common sign. If you see that several subclasses share almost identical algorithms, with only a few steps being different, the Template Method pattern can be used to eliminate code duplication.
Complex conditional logic
If you see complicated conditional statements selecting different versions of the same algorithm in a base or utility class, it might be worth considering the Template Method pattern. With this pattern, you can isolate these variations in separate methods within subclasses.
Need to extend part of an algorithm, not all of it
Sometimes, you need to let subclasses extend only particular parts of a larger algorithm without allowing them to change the algorithm itself. The Template Method pattern lets subclasses redefine certain steps of an algorithm without changing its structure.
The algorithm has mandatory and optional parts
If some parts of an algorithm are optional, the Template Method pattern can be used to create " hooks". A hook is a method declared in the abstract class, but only given an empty or default implementation. Subclasses can extend these hooks, but they're not required to.
Algorithm has a specific sequence of operations
If an algorithm must execute in a certain order (for example, validating input, processing, and then outputting results), this can be enforced with a Template Method.
However, it's worth noting that while these signs might suggest using the Template Method pattern, it's not always the best or only solution. The decision depends on the exact nature of the problem and the context in which it's being solved. Other design patterns, like Strategy or State, might be more appropriate for some cases.
Time To Transition From JavaScript To TypeScript
Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.
SEE COURSE DETAILSWhat Can You Do Next 🙏😊
If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for software developers.