Strategy Pattern — A Quick Guide
Design Patterns: Strategy Pattern
--
“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.”
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 furCat 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)
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.