What is Strategy Pattern?
Strategy Pattern is behavioral pattern that defines a family of algorithms, encapsulates each one by putting them into a separate class, and makes them interchangeable.
A family of algorithms refers to a set of algorithms that do the same but differently. Sorting algorithms are good example since they do the same things, SORTING! But process is not the same such as merge sort, bubble sort, quick sort.
When to use it?
Use Strategy pattern when you have many possible variation of algorithms.
For example, for a set of data, there's many possible searching algorithms such as linear search, binary search, jump search. Using Strategy pattern let us to change strategy dynamically with help of composition (you'll see in UML), that is, you can change searching algorithm for the set of data at runtime.
A good indication for applicability of strategy pattern is if we find different algorithms/behaviors in our methods which are selected with conditional statements like if-else or switch-case.
Problem
Assume we're developing card game system. Each concrete hero class extends Hero class and implement its own behavior such as different greeting styles.
But what if we want to introduce another hero who also uses an axe? We have to write the same code as useWeapon
method in Warrior
for that hero. In the future, if we want to change useWeapon implementation for an axe, we have to modify the method as many as heroes who use an axe.
Solution
Hero
Maintains reference toWeaponStrategy
object.setWeapon
method allows client to dynamically change hero's behavior at runtime.Hero
class can calluseWeapon
method likeweapon.useWeapon
.Concrete heroes
Provides specific behavior for each hero.WeaponStrategy
Provides common interface for all the strategies. In this way, client code can program to interface not implementation.Concrete Strategies
Define concrete implementation for using weapons.
With this structure, if we want to add another hero who will use an axe, we just add that concrete hero class and use setWeapon
method. Our strategies are now decoupled from client code which is easier to maintain.
Also, strategies are interchangeable. Let's say our new version introduces the system that a hero can attach any weapon, Strategy pattern easily accomplish this because we can switch strategies dynamically at runtime.
Structure
- Client only see context class.
- Strategies are decoupled from client code by composition.
- Context uses strategy object to run actual algorithm e.g.
strategy.runAlgorithm()
. - We can define multiple concrete strategies that implements actual algorithms in different way.
Implementation in Java
/*
Content in Strategy pattern
*/
public abstract class Hero {
private WeaponStrategy weapon;
public Hero() {
this.weapon = new NoWeaponStrategy();
}
public abstract void greet();
public void surrender() {
System.out.println("You lose");
}
public WeaponStrategy getWeapon() {
return weapon;
}
public void setWeapon(WeaponStrategy weapon) {
this.weapon = weapon;
}
}
/*
Concrete content in Strategy pattern
*/
public class Warrior extends Hero {
@Override
public void greet() {
System.out.println("Die with honor!");
}
}
/*
Strategy in Strategy pattern
Interface for algorithms implementation
*/
public interface WeaponStrategy {
void useWeapon();
}
/*
Concrete strategy
*/
public class NoWeaponStrategy implements WeaponStrategy {
@Override
public void useWeapon() {
System.out.println("Can't attack, you need a weapon!");
}
}
/*
Concrete strategy
*/
public class AxeStrategy implements WeaponStrategy {
@Override
public void useWeapon() {
System.out.println("Chopping with an axe!");
}
}
/*
Client can use different strategies (or algorithms) dynamically
*/
public class Client {
public static void main(String[] args) {
Hero warrior = new Warrior();
// warrior hasn't equipped a weapon
warrior.getWeapon().useWeapon();
// warrior equips an axe
warrior.setWeapon(new AxeStrategy());
warrior.getWeapon().useWeapon();
}
}
Output:
Can't attack, you need a weapon!
Chopping with an axe!
Notice warrior has used NoWeaponStrategy
at the beginning, then by calling setWeapon
method, warrior changed his strategy to AxeStrategy
. Thus, it's proven that Strategy pattern let us to change algorithm at runtime.
Pitfalls
- Since client code configures strategy for a context, client needs to know each strategy implementation.
You can check all the design pattern implementations here.
GitHub Repository
P.S.
I'm new to write tech blog, if you have advice to improve my writing, or have any confusing point, please leave a comment!
Thank you for reading :)
Top comments (1)