Strategy Vs State Vs Template Design Patterns
Tags: javascript, typescript, designpatterns
Published: 2022-03-20 16:12:31

---
title: Strategy Vs State Vs Template Design Patterns
published: true
date: 2022-03-20 15:03:15 UTC
tags: #javascript #typescript #designpatterns
canonical_url: https://mayallo.com/strategy-vs-state-vs-template-design-patterns/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/122yrvgin8y7j58tqhve.jpg
---

# Introduction

As you know, **Design Patterns** are special solutions designed by experts for common problems. They are not a ready-to-use library or a package, conversely, they are general concepts you can follow to solve your problem regardless of the programming language you use.

There are three major categories for these patterns which are **Creational, Structural,** and **Behavioral Design Patterns**.

In this post, we will know the differences between three of so close **Behavioral Design Patterns** which are **Strategy, State** , and **Template**.

> _We will take the same example to just define the differences easily not to decide that this pattern is the perfect fit for this situation._

Let's imagine a scenario in which a user can choose from different payment gateways to pay for his order or the payment gateway is predefined in the API.

# Strategy

In **Strategy** , you can define a family of strategies (algorithms) that can be used interchangeably to solve a specific problem.

![strategy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsdl48ql79fetv2ahv65.jpg)


As you can see, if we want to add a new payment gateway, all we have to do is just adding a new strategy implementing this gateway logic which respects the **[Open-Closed Principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)** perfectly.

Let's jump right into our example:

```typescript
interface IGateway {
    gatewayAuth(): void
    pay(): void
}

// Strategies
class Gateway1 implements IGateway {
    gatewayAuth() { console.log('Gateway1 => gatewayAuth()'); }
    pay() { console.log('Gateway1 => pay()'); }
}

class Gateway2 implements IGateway {
    gatewayAuth() { console.log('Gateway2 => gatewayAuth()'); }
    pay() { console.log('Gateway2 => pay()'); }
}

// Context
class Order {
    constructor(private gateway: IGateway) {} // Strategy injection at runtime

    private createOrder() { console.log('Order => createOrder()'); }

    pocessOrder() {
        if (!this.gateway) { throw new Error('No gateway!'); }
        this.gateway.gatewayAuth();
        this.gateway.pay();
        this.createOrder();
    }
}

// Client
const gateway2 = new Gateway2();
// You can change the entire algorithm by injecting another strategy
const order = new Order(gateway2);
order.pocessOrder();

```

From the previous example, we note that the **Strategy** pattern lets you change the **Order (Context)** object behavior **_at the runtime_** by injecting a specific payment gateway and its behavior will remain unchanged for the rest of the lifespan of the **Order (Context)** object.

### When should you use the Strategy pattern?

Simply, when you have many variants (strategies) which can be used interchangeably and you want to switch between them just **_at the runtime (at the Context creation time)._**

If your **Context** object has many `if...else` statements, this might be an indicator to replacing them with **Strategies**.

# State

The **State** pattern is a specialization of the **Strategy** pattern and is so close to it.

![state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czq1xh5kf38u0j2ida7n.jpg)


As you can see, the **State** pattern almost looks like the **Strategy** pattern. And as **Strategy** , if we want to add a new payment gateway, all we have to do is adding a new **State** which also respects the **[OCP](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)**.

Let's jump right into our example:

```typescript
interface IGateway {
    gatewayAuth(): void
    pay(): void
}

// States
class Gateway1 implements IGateway {
    gatewayAuth() { console.log('Gateway1 => gatewayAuth()'); }
    pay() { console.log('Gateway1 => pay()'); }
}

class Gateway2 implements IGateway {
    gatewayAuth() { console.log('Gateway2 => gatewayAuth()'); }
    pay() { console.log('Gateway2 => pay()'); }
}

// Context
class Order {
        private currentGateway!: IGateway;
    private gateways: { [key: string]: IGateway } = {
        gateway1: new Gateway1(),
        gateway2: new Gateway2()
    }

    constructor() {
        this.changeGateway('gateway1'); // Defualt State
    }

    // State transition
    changeGateway(gatewayName: string) {
        this.currentGateway = this.gateways[gatewayName];
    }

    private createOrder() { console.log('Order => createOrder()'); }

    pocessOrder() {
        if (!this.currentGateway) { throw new Error('No gateway!'); }
        this.currentGateway.gatewayAuth();
        this.currentGateway.pay();
        this.createOrder();
    }
}

// Client
const order = new Order();
order.changeGateway('gateway2');
order.pocessOrder();
// You can switch between States dynamically during the lifespan of the Order object
order.changeGateway('gateway1');
order.pocessOrder();

```

From the previous example, you may note here you can switch between the payment gateways ( **States** ) dynamically for the rest of the lifespan of the **Order (Context)** object.

### Where should you implement the State transition?

- **_Client_** : As we do in the previous example which decreases the coupling, but unfortunately this isn’t the case all the time.
- **_Context_** : In this case, the **Context** will know about all the possible states and how to transition between them which increases the coupling.
- **_State_** : Every state can transition between each other which increases the coupling as well between the states.

### So what is the difference between Strategy and State?

- In the **Strategy** pattern, the **Context** behavior changes once by injecting a specific strategy and remains unchanged for the rest of its lifespan **.** Conversely, in the **State** pattern, the **Context** behavior can be changed dynamically during the rest of its lifespan by switching between its **States**.
- In the **State** pattern, if the state transition occurs inside each state then every state will know about each other, in contrary in the **Strategy** pattern, strategies don’t know anything about each other.

### When should you use the State pattern?

Simply, when your object ( **Context** ) has many states and changes its behavior frequently depending on these states during the rest of its lifespan.

Like **Strategy** , if your **Context** object has many `if...else` statements, this might be an indicator to use the **State** pattern.

# Template

The **Template** pattern defines the skeleton of an algorithm in the superclass and overrides specific steps of this algorithm by its subclasses without changing its structure.

![template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hgaxna1p4r1hp8pqpmj.png)

From the diagram, we note that the superclass **(Order)** lets its subclasses override specific tasks of its algorithm. As a result, if we want to add a new payment gateway all we have to do is adding a subclass that overrides these specific tasks.

### So what is the difference between Strategy and Template?

- **Strategy** varies the entire algorithm via its strategies.
- **Template** varies specific parts of the algorithm by subclasses.

Let's jump right into our example:

```typescript
// Superclass
abstract class Order {
    // Specific parts of the algorithm will be overridden by subclasses
    abstract gatewayAuth(): void
    abstract pay(): void

    // While other parts remain unchanged
    private createOrder() { console.log('Order createOrder()'); }

    // The algorithm skeleton
    processOrder() {
        this.gatewayAuth();
        this.pay();
        this.createOrder();
    }
}

// Subclasses (Override specific parts of the algorithm)
class Gateway1 extends Order {
    gatewayAuth() { console.log('Gateway1 => gatewayAuth()'); }
    pay() { console.log('Gateway1 => pay()'); }
}

class Gateway2 extends Order {
    gatewayAuth() { console.log('Gateway2 => gatewayAuth()'); }
    pay() { console.log('Gateway2 => pay()'); }
}

// Client
const gateway2 = new Gateway2();
// Subclass is responsible to run the main algorithm
gateway2.processOrder();

```

From the previous example, we now deal directly with the subclasses which are responsible to run the template method **(processOrder).**

### When should you use the Template pattern?

You should use the **Template** pattern if you have an algorithm and you want to override specific steps (not the entire algorithm) of it with interchangeable subclasses.

# Conclusion

So, what is the best pattern? as always, it depends, it is up to the developer who should understand the general concepts and the pros and cons of each pattern and as a result, decides what is better for his situation.

# Resources

[Refactoring Guru](https://refactoring.guru/)

[Source Making](https://sourcemaking.com/)

Nodejs Design Patterns 3rd edition