Part 04: Strategy Design Pattern

Part 04: Strategy Design Pattern

Strategy is a behavioral design Pattern, it lets you define a family of algorithms for a particular task, put them in different classes and use their objects interchangeably.

Suppose we have a single class that performs a lot of actions, the class would be too complex and every time we need to add something we will have do make a lot of changes, the complexity will increase and so will the size of the code.

Strategy pattern suggests to make different classes for different algorithms and call those classes strategies and call the main class context. It should have a field which stores a reference to one of the strategy class object and strategy object will perform the specified task.

Now, the context is not responsible for picking an algorithm for a specific case, the desired strategy will be passed to the context by client. It is just an independent generic interface who knows about a single method which triggers the algorithm in strategy. This makes our application extensible and modifiable without hassle of changing all of the code.

For example. we need to make a navigation application which shows routes in a city, routes must show proper navigation for driving, walking and buses. If we define algorithms for all three of them in a single class, it will get too complex and huge, so we divide them into three strategy classes and we will make a context class which will have a reference of a strategy object. When the client selects routes for car, at runtime car strategy will be chosen, when it chooses routes for buses, at runtime bus strategy will be chosen.

Structure

strategy.jpg

Implementation

In our example I have chosen a simpler example of mathematical operations addition, subtraction and multiplication as strategies and at runtime we will be changing our strategies. Let's take a look.

let Context = function() {
  // by default operation is set to Addition
  this.operation = new Addition();
}

Context.prototype = {
  // sets strategy
  setStrategy: function(operation) {
    this.operation = operation;
  },
  // executes the execute function of the strategy
  execute: function(a, b) {
    return this.operation.execute(a, b);
  }
}

function Multiplication() {
  this.execute = function(a, b) {
    return a * b;
  }
}

function Addition() {
  this.execute = function(a, b) {
    return a + b;
  };
}

function Subtraction() {
  this.execute = function(a, b) {
    return a - b;
  }
}

function run() {
  // make a new context
  let context = new Context();

  context.setStrategy(new Addition());
  console.log(context.execute(1, 2));

  context.setStrategy(new Subtraction());
  console.log(context.execute(1, 2));

  context.setStrategy(new Multiplication());
  console.log(context.execute(1, 2));
}

run();

When to use strategy pattern

  • When you have to use different variants of an algorithm and at runtime switch from one algorithm to another.
  • When you have different similar classes that execute differently at runtime.
  • When you want to isolate business logic from the algorithms.

Advantages

  • You can swap algorithms used in a object at runtime.
  • Implementation details of algorithms will be isolated.
  • You can add new strategies without having to change the context.

Disadvantages

  • Your application will over-complicate if you have a few algorithms and they don't have to be changed at runtime.
  • Client must know all of the strategies to select an appropriate one.