Understanding Strategy and Template Patterns: Key Differences and Practical Examples
Amit Kumar
Senior Specialist Software Engineer - Angular, React, Micro frontends, Nx Monorepo, Web3, Smart Contracts
Design patterns are proven solutions to common software design problems that can help make code more modular, reusable, and maintainable. In this article, we explore two important behavioral design patterns: the Strategy Pattern and the Template Pattern. While both patterns allow for flexible and customizable behavior, they are applied in different contexts and offer distinct approaches to solving design challenges.
The Strategy Pattern enables the dynamic selection of algorithms or behaviors at runtime, promoting flexibility and extensibility in our codebase. On the other hand, the Template Pattern defines the structure of an algorithm while allowing subclasses to alter specific steps without changing the overall flow.
In the following sections, we will dive deeper into the characteristics of each pattern, along with practical examples to illustrate their usage, similarities, and differences. Whether we're building algorithms, workflows, or process-driven applications, understanding these patterns can help us write cleaner, more maintainable code.
Strategy Pattern
The Strategy Pattern is a behavioral design pattern that enables selecting an algorithm's behavior at runtime. In JavaScript, it is implemented by defining a family of algorithms (or strategies), encapsulating each one in a separate class or function, and making them interchangeable.
Components of the Strategy Pattern:
Here’s how we can implement it in JavaScript:
// Strategy Interface (optional in JavaScript but implied)
class PaymentStrategy {
pay(amount) {
throw new Error("Method 'pay' should be implemented");
}
}
// Concrete Strategies
class CreditCardPayment {
pay(amount) {
console.log(`Paid $${amount} using Credit Card.`);
}
}
class PayPalPayment {
pay(amount) {
console.log(`Paid $${amount} using PayPal.`);
}
}
class BitcoinPayment {
pay(amount) {
console.log(`Paid $${amount} using Bitcoin.`);
}
}
// Context
class PaymentContext {
constructor(strategy) {
this.strategy = strategy; // The chosen payment strategy
}
setStrategy(strategy) {
this.strategy = strategy; // Dynamically change the strategy
}
processPayment(amount) {
this.strategy.pay(amount); // Delegate to the chosen strategy
}
}
// Usage
const paymentContext = new PaymentContext(new CreditCardPayment());
paymentContext.processPayment(100); // Paid $100 using Credit Card.
paymentContext.setStrategy(new PayPalPayment());
paymentContext.processPayment(200); // Paid $200 using PayPal.
paymentContext.setStrategy(new BitcoinPayment());
paymentContext.processPayment(300); // Paid $300 using Bitcoin.
Key Features:
Functional Approach (Without Classes)
We can also implement the Strategy Pattern in JavaScript using plain functions:
// Concrete Strategies
const creditCardPayment = (amount) => console.log(`Paid $${amount} using Credit Card.`);
const payPalPayment = (amount) => console.log(`Paid $${amount} using PayPal.`);
const bitcoinPayment = (amount) => console.log(`Paid $${amount} using Bitcoin.`);
// Context
class PaymentContext {
constructor(strategy) {
this.strategy = strategy;
}
setStrategy(strategy) {
this.strategy = strategy;
}
processPayment(amount) {
this.strategy(amount);
}
}
// Usage
const paymentContext = new PaymentContext(creditCardPayment);
paymentContext.processPayment(100); // Paid $100 using Credit Card.
paymentContext.setStrategy(payPalPayment);
paymentContext.processPayment(200); // Paid $200 using PayPal.
paymentContext.setStrategy(bitcoinPayment);
paymentContext.processPayment(300); // Paid $300 using Bitcoin.
Use Cases:
By using the Strategy Pattern, we keep our code modular, maintainable, and easy to extend.
Template Pattern
The Template Pattern is a behavioral design pattern that defines the skeleton of an algorithm in a base class (abstract or parent class) but lets subclasses override specific steps of the algorithm without changing its structure. It provides a "template" method in the base class that dictates the steps of the algorithm, some of which can be implemented or modified by subclasses.
Key Features of Template Pattern:
Algorithm Structure:
Code Reuse:
Control Inversion:
领英推荐
Example of Template Pattern:
Let's consider a simple example of creating beverages like coffee and tea.
class Beverage {
prepareRecipe() {
this.boilWater();
this.brew();
this.pourInCup();
this.addCondiments();
}
boilWater() {
console.log("Boiling water");
}
pourInCup() {
console.log("Pouring into cup");
}
// Steps to be implemented by subclasses
brew() {
throw new Error("This method should be overridden!");
}
addCondiments() {
throw new Error("This method should be overridden!");
}
}
class Coffee extends Beverage {
brew() {
console.log("Brewing coffee");
}
addCondiments() {
console.log("Adding sugar and milk");
}
}
class Tea extends Beverage {
brew() {
console.log("Steeping the tea");
}
addCondiments() {
console.log("Adding lemon");
}
}
// Usage
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
Strategy Pattern vs. Template Pattern
Similarities:
Behavioral Patterns:
Polymorphism:
Avoiding Duplicated Code:
Differences:
When to Use Which Pattern?
Use Strategy Pattern:
Use Template Pattern:
#designpatterns #softwareengineering #programming #developer #coding #strategypattern #templatepattern #softwaredevelopment #technology