Template Method Design Pattern in JavaScript

1. Definition

The Template Method Design Pattern defines the structure of an algorithm in a method of a base class, but delays some steps to subclasses. This allows subclasses to override specific steps without changing the overall structure and sequence of the algorithm.

2. Problem Statement

Imagine an application with a series of operations that need to be executed in a specific sequence, but some operations within this sequence can vary. Coding every variation of the sequence can quickly become unmanageable and redundant.

3. Solution

Use the Template Method pattern to move the invariant parts of the algorithm into a base class, while specific steps that can vary are either made abstract or implemented with a default behavior. Subclasses will then provide concrete implementations for these variant steps.

4. Real-World Use Cases

1. Database record synchronization where steps like validation and logging are common, but the actual database update mechanism might vary.

2. Building applications where certain phases are consistent, like setup and cleanup, but the actual application processing logic differs.

5. Implementation Steps

1. Create an abstract base class with a template method defining the skeleton of the algorithm.

2. Within this template method, include abstract methods for the variant parts.

3. Subclasses will provide concrete implementations for the abstract methods.

6. Implementation in JavaScript

// Abstract Class
class AbstractRecipe {
    // This is the template method.
    prepareRecipe() {
        this.boilWater();
        this.brew();
        this.pourInCup();
        this.addCondiments();
    }
    boilWater() {
        console.log("Boiling water");
    }
    // Abstract methods.
    brew() {}
    addCondiments() {}
    pourInCup() {
        console.log("Pouring into cup");
    }
}
// Concrete Class 1
class Coffee extends AbstractRecipe {
    brew() {
        console.log("Brewing coffee");
    }
    addCondiments() {
        console.log("Adding sugar and milk");
    }
}
// Concrete Class 2
class Tea extends AbstractRecipe {
    brew() {
        console.log("Steeping the tea");
    }
    addCondiments() {
        console.log("Adding lemon");
    }
}
// Client Code
const coffee = new Coffee();
coffee.prepareRecipe();
const tea = new Tea();
tea.prepareRecipe();

Output:

Boiling water
Brewing coffee
Pouring into cup
Adding sugar and milk
Boiling water
Steeping the tea
Pouring into cup
Adding lemon

Explanation:

1. AbstractRecipe provides a template method called prepareRecipe() that contains a series of steps to prepare a drink.

2. The common steps, like boiling water and pouring into a cup, are implemented in the AbstractRecipe class.

3. Variant parts, such as brewing and adding condiments, are left abstract or with default behavior.

4. Concrete subclasses like Coffee and Tea provide specific implementations for the abstract methods, tailoring the steps to their needs.

5. The client code shows how the full sequence of steps is preserved, even when certain steps have different implementations.

7. When to use?

Use the Template Method Pattern when:

1. A series of steps are executed in a specific sequence, but some steps can vary.

2. Common behavior among subclasses should be factored out to avoid redundancy.

3. Subclasses need to extend only certain parts of a large algorithm, without altering its structure.


Comments