TypeScript Template Method Pattern Example

1. Definition

The Template Method Design Pattern defines the program skeleton in an algorithm within a method, but delays some steps to subclasses. It allows subclasses to redefine certain steps of an algorithm without changing its structure.

2. Problem Statement

Suppose you are developing a data processing application where there are several steps in the processing flow, such as data loading, processing, and saving. These steps remain consistent, but the way each step is executed can differ based on the type of data source.

3. Solution

The Template Method Pattern suggests moving the invariant parts of the algorithm into a separate abstract class, while moving the variable parts, the steps that can be overridden, into concrete subclasses. This way, the general algorithm structure remains unchanged, while subclasses provide specific implementations for steps they wish to modify.

4. Real-World Use Cases

1. Workflow processes where steps are defined but implementation differs.

2. Compilers for different programming languages.

3. Bread-making processes: the steps remain the same, but ingredients might change.

5. Implementation Steps

1. Identify the invariant (common) steps and place them in a "template method".

2. Declare methods for every variable step in an abstract class.

3. Implement the variable steps in concrete subclasses.

6. Implementation in TypeScript

// Abstract class with the template method
abstract class DataProcessor {
    // This is the template method
    process(): void {
        this.loadData();
        this.parseData();
        this.saveData();
    }
    abstract loadData(): void;
    abstract parseData(): void;
    abstract saveData(): void;
}
// Concrete class 1
class XMLProcessor extends DataProcessor {
    loadData(): void {
        console.log("Loading XML data.");
    }
    parseData(): void {
        console.log("Parsing XML data.");
    }
    saveData(): void {
        console.log("Saving XML data.");
    }
}
// Concrete class 2
class JSONProcessor extends DataProcessor {
    loadData(): void {
        console.log("Loading JSON data.");
    }
    parseData(): void {
        console.log("Parsing JSON data.");
    }
    saveData(): void {
        console.log("Saving JSON data.");
    }
}
// Client code
const xmlProcessor = new XMLProcessor();
xmlProcessor.process();
const jsonProcessor = new JSONProcessor();
jsonProcessor.process();

Output:

Loading XML data.
Parsing XML data.
Saving XML data.
Loading JSON data.
Parsing JSON data.
Saving JSON data.

Explanation:

The DataProcessor abstract class defines the structure of the data processing algorithm in the process method. This method is the so-called "template method". Each step in this method (loadData, parseData, saveData) can have varied implementations, so they're declared as abstract in the base class. The concrete subclasses XMLProcessor and JSONProcessor provide the actual implementations for these steps.

7. When to use?

Use the Template Method Pattern when:

1. You want to let clients extend only particular steps of an algorithm.

2. Various implementations of algorithm steps are required.

3. You want to pull the duplicate code into a superclass.


Comments