Strategy Pattern — A Quick Guide

Design Patterns: Strategy Pattern

Emre Tanrıverdi
3 min readJul 17, 2020

Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use them.”

Photo by Kelly on Unsplash

Aside from formal definition, Strategy Pattern is widely used when you need to switch your algorithm or strategy in different places of your code.

Simple Example:

Suppose you build a game that has a Cat class that implements a Diet class. But let’s say your cat gained too much weight and now it needs to go on a diet that will help it lose weight for its health.

In this case, you can implement a Strategy Pattern such as:

interface EatBehavior {
public void eat();
}

diet types that implements the eat behavior

public class NormalDiet implements EatBehavior {
@Override
public void eat() {
// normal food
}
}
public class LosingWeightDiet implements EatBehavior {
@Override
public void eat() {
// healthy food
}
}

cat class that HAS-A eat behavior

public abstract class Cat {

EatBehavior eatBehavior;

public Cat(){}

public void eat() {
eatBehavior.eat();
}
}

And the client code would be like this:

cat.eat();            // Cat eats as usual.cat.setEatBehavior(new LosingWeightDiet());cat.eat();           // Cat eats with a healthier diet.

Strategy Patterns can also help you assign different behaviors for different subtypes.

Let’s say you have a spyhnx cat (a species of cat that doesn’t have any fur) and a tabby cat (or any other cat species that has a fur).

You can easily update your classes as follows:

interface EatBehavior {
public void eat();
}
interface DisplayBehavior {
public void display();
}

fur types that implements the display behavior

public class HasFur implements DisplayBehavior {
@Override
public void display() {
// display with fur
}
}
public class NoFur implements DisplayBehavior {
@Override
public void display() {
// display without fur
}
}

a cat class that IS-A Cat type and HAS-A eat and display behavior

public class Sphynx extends Cat {

EatBehavior eatBehavior;
DisplayBehavior displayBehavior;

public Sphynx() {
eatBehavior = normalDiet();
displayBehavior = noFur();
}

public void eat() {
eatBehavior.eat();
}

public void display() {
displayBehavior.display();
}
}

another cat class that IS-A Cat type and HAS-A eat behavior with a different display behavior

public class Tabby extends Cat {

EatBehavior eatBehavior;
DisplayBehavior displayBehavior;

public Tabby() {
eatBehavior = normalDiet();
displayBehavior = hasFur();
}

public void eat() {
eatBehavior.eat();
}

public void display() {
displayBehavior.display();
}
}

And the client code would be like this:

Cat spyhnx = new Spyhnx();
sphynx.display(); // displays cat without fur
Cat tabby = new Tabby();
tabby.display(); // displays cat with fur

As seen above, it can also help you separate concerns of classes.

If one day you want to remove fur from the tabby for your game, you can just change how displayBehavior is set in the Tabby class and the client won’t need to be notified of this change.

Each class will only care of its own. (Single Responsibility Principle)

Photo by Kelly on Unsplash

Real-Life Example:

Suppose you are writing a software that will show weather forecasts but you want to store the user information in a database and weather information in another database.

different database types that implements the database strategy

public class PostgreStrategy implements DatabaseStrategy {
@Override
public void save() {
// save to PostgreSQL
}
}
public class CouchbaseStrategy implements DatabaseStrategy {
@Override
public void save() {
// save to Couchbase
}
}

The client code:

DatabaseContext db = new DatabaseContext();db.setDatabaseStrategy(new PostgreStrategy());
db.save(userInformation);
db.setDatabaseStrategy(new CouchbaseStrategy());
db.save(weatherInformation);

Again, if one day you want to change the way how PostgreStrategy or CouchbaseStrategy works, you won’t need to touch the client code.

In short, Strategy Pattern helps us to dynamically change the way our components work as we write code and separates our concerns.

Thank you for reading and being a part of my journey!

Reference(s)

  • Head First Design Patterns. by Eric Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra. Released October 2004. Publisher(s): O’Reilly Media, Inc.

--

--

Emre Tanrıverdi
Emre Tanrıverdi

No responses yet