Design Pattern “Strategy” applied with TypeScript
By: Ruben Acevedo
Tags: Development, Strategy, Nodejs, Typescript, Design Patterns

Before we start coding, we need to understand why and when we use this design pattern.

Imagine that you want to watch the famous tv series “Friends” on your TV.

The problem is that Friends can be watched in different platforms as Netflix, tv channel Warner, etc. So, how do we create an algorithm to apply different ways to watch the same thing?

Strategy pattern help us do exactly that in the best way possible.

In resume,

Design Pattern “Strategy” helps us implement different solutions to the same problem.

In this pattern, different strategies are applied to the same context.

Strategy:

Responsible for implementing a singular solution for the problem. In our example, “Netflix” would be a strategy, due to implement “Friends” in a different way that other streamings or tv channels.

Context:

Is responsible for applying the interface that the strategies would use. It doesn’t know what the strategies are doing, it just knows that they need to apply it.

Here’s a diagram showing the flow of the pattern:

In this case, Friends applies the function “Watch()” in the context and the strategies “Netflix” and “Warner Channel” implement the function Watch() to their singular procedures

Let’s code!

The first thing to do is to create an interface with the function watch().

Interface

export default interface IWatch { watch() }

Context

The next step is to create the context.

First thing context will do is receive the strategy that will apply the function watch().

After that it will create the function that connects that strategy with the function inside the interface.

import IWatch from ‘./interface’ export default class Context { private _strategy: IWatch constructor(strategy: IWatch) { this._strategy = strategy } public watch = () => { this._strategy.watch() } }

Now that we have our interface and our context, we’ll create the strategies and their singular implementations of the interface IWatch.

Strategy 1 — Netflix

import IWatch from ‘./interface’ export default class Netflix implements IWatch { watch = () => { console.log(‘You are watching Friends on Netflix!’) } }

Strategy 2 — Warner Channel

import IWatch from ‘./interface’ export default class Warner implements IWatch { watch = () => { console.log(‘You are watching Friends on Warner!’) } }

As we can see, both of them just console.log() a text saying that you’re watching Friends in their channel.

index.ts

Now, that all our relations are applied, we just need to create the objects and use them as we want. We’ll do that in a file called index.ts.

import Context from ‘./context’ import Netflix from ‘./strategyNetflix’ import Warner from ‘./strategyWarner’ const friendsOnNetflix = new Context(new Netflix()) const friendsOnWarner = new Context(new Warner()) friendsOnNetflix.watch() friendsOnWarner.watch()

As you can see, we instantiate the Context and inside it we instantiate the strategy we want.

That way we can always implement the channel we want.

Conclusion

This design pattern is perfect for those who wish to apply different solutions to the same kind of problem. It is very easy to maintain, has a great performance and is very readable.

If you have any doubts or suggestions feel free to contact me.

Thanks! :)