The Strategy Design Pattern

One of the simpler and more useful tools in OOD is the Strategy design pattern. It gives you a lot of flexibility and it’s a great introduction to concepts in software modeling like polymorphism and inversion of control (IOC). The Gang of Four explain the intent of the Strategy pattern:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

Before we get to some of the OO stuff in the pattern, and why it matters, let’s take a look at the demo we’ll be using. An N-body simulator physically models bodies of varying mass and calculates the forces between them. The fun part is setting up different initial conditions. Even with the same physics rules, you can get an impressive variety of behavior by changing the initial conditions (e.g., the number of bodies, their placement and individual mass). You can also change the global conditions like the gravity constant, damping and the speed of the simulation. Since we want to encapsulate those aspects of the simulator, the Strategy pattern is perfect.

The Strategy can be implemented in pretty much any OO language, but we’re using JavaScript here so we can see the results of the demo in the browser. We’re also using the excellent Paper.js library to handle some of the 2D drawing and a little bit of vector math.

The demo has five different Strategy classes that can be changed using the buttons. As you press the buttons, the simulator plugs in a different Strategy class. In keeping with the definition above, note that each N-Body Strategy is interchangeable and, as a group, can be thought of as a family of algorithms.

In our simulator, it’s important to understand the responsibilities of the N-body Strategy classes. Each class is designed to

1. Set the number of bodies
2. Set the location, mass, color, size and (optional) the initial velocity of each body
3. Accumulate the forces acting on the bodies each cycle
4. Integrate the positions of the bodies each cycle

In the general example case, a Strategy class has a single method that’s implemented. That method is called `execute()`—as in execute the algorithm of this Strategy. The design pattern doesn’t require whether the method is called once, or every cycle or even that it’s named execute (it’s always better to name it something a little more descriptive). The pattern only requires the `execute()` method be named the same in each Strategy and can be called the same way by other classes or clients. The key is that it’s named the same, but implemented differently. This is polymorphism: same name, different behavior.

The Strategy design pattern also has another component, the Context class. The Context acts as a parent to the Strategy classes, keeping a collection of Strategies. The Context handles how Strategy classes are added, activated and used in the application.

In our case, the execute-like method is called `simulate()`. Each cycle, the forces affecting every simulated body are calculated and their positions are integrated. The `simulate()` method takes care of responsibilities three and four in the list above. The constructor of each N-Body Strategy class takes care of the first and second. Even though the initial conditions are in the constructor, they still are very much part of each Strategy’s algorithm.

The `NBodyContext`class is the Context for the N-body Strategy classes. Let’s take a look at the code for the main application cycle in `NBodyContext`.

```NBodyContext.prototype.run = function () {
var \$this = this;
view.onFrame = function (event) {
\$this.simStrategy.simulate();
\$this.draw();
}
}```

Notice that the `run()` method in `NBodyContext` doesn’t care which Strategy is currently active. This is why polymorphism is so powerful. As long as the interface of each Strategy class remains consistent, we don’t have to do any object testing or use any conditionals to alter the behavior of the system. It just works.

If you’re interested in OOD you’re probably familiar with the concept favor composition over inheritance. The Strategy pattern is very much compositional. The `NBodyContext` class is composed of the current Strategy class. An alternative would be to subclass the Context each time you wanted different behavior in the simulation, but the behavior would then be hardwired into the class. You’d lose the flexibility of just changing the behavior and you’d have to carry around all the higher level code—like the main application loop—inherited in each Context subclass.

The use of the Strategy pattern is compositional in nature, but that doesn’t mean a Strategy class can’t take advantage of inheritance. That’s what we’ve done with `AbstractStrategy`. All Strategy classes inherit from`AbstractStrategy` and, by default, they only have to setup the initial conditions of a simulation. Everything else is inherited. As a result, classes like `SpiralStrategy` are quite simple.

```"use strict";

/*
* A strategy that creates a spiral configuration of bodies,
* increasing in mass and size.
*/
var SpiralStrategy = function () {

AbstractStrategy.call(this,
{timeStep:1/20, gravity:0.1, damping:0.999});

var scale = 20;
var count = 150;
var mssCoef = 0.01;

var colorA = new Color(1.0, 0.0, 1.0, 0.9);
var colorB = new Color(1.0, 0.5, 0.0, 0.9);

var c = view.center.clone();
c.x -= 200;

for (var i = 1; i <= count; i++) {

c.x += Math.sin(i * 0.1) * scale;
c.y += Math.cos(i * 0.1) * (scale += 1);

var mss = i * mssCoef + 1;
var color = (i % 2 == 0) ? colorA : colorB;

new CircleBody(c.x, c.y, rad, mss, color));
}
}

SpiralStrategy.prototype =
Object.create(AbstractStrategy.prototype);
SpiralStrategy.prototype.constructor = SpiralStrategy;
```

The default behavior of our Strategy child classes uses the `accumulateForces()` method inherited from `AbstractStrategy`. That accumulator doesn’t take into account the distance of the bodies when determining forces.

If we want to change the way a child class behaves, respective to its parent, we can override a method in the child class. That’s what we’re doing in the `DistanceForceStrategy` class. The overridden `accumulateForces()` method adds distance to the force equation. Similarly, the `MouseEventStrategy` class overrides the `accumulateForces()` to allow the mouse to affect the behavior of the simulation.

There’s a worthwhile distinction between `MouseEventStrategy` and `DistanceForceStrategy`. The former overrides the `accumulateForces()` method and calls that method in the parent abstract class. Then it just adds a little extra code to update the mouse behavior.

```MouseEventStrategy.prototype.accumulateForces = function () {
AbstractStrategy.prototype.accumulateForces.call(this);
this.mouseBody.position = this.mousePoint;
}```

The `DistanceForceStrategy` class, on the other hand, completely overrides the same method without calling it in the superclass. These are two flexible approaches to subclassing and overriding methods. Overall you should favor composition, but inheritance is very powerful where appropriate. Learning to spot good inheritance vs. bad inheritance is key to becoming a good architect.

So what makes this an example of IOC? Well, it’s a bit of a simple demo, but its behavior is delegated to modular components—the Strategy classes. The reusable, unchanging part of the simulator—the container—makes calls to the pluggable, swappable Strategy classes. Only the Strategy classes need to be added or altered to extend and change the system behavior. For example, you could scrap all the current Strategy classes and write twenty new ones while the overarching system remains the same. Anytime you have a modular, Strategy-based architecture like this, it’s almost always an example of IOC.

2. The `CircleBody` class is responsible for the actual integration algorithm. Is this good design? What if you wanted to change the integrator during runtime? The current one is Verlet integration. What if you wanted to swap it to Euler?