Design Patterns Demystified: Exploring the Strategy Pattern

Design patterns are like a secret recipe that experienced software developers use to create robust, maintainable, and extensible code. In this blog post, we'll be exploring a delicious pattern - the Strategy Design Pattern - and how it can spice up your coding skills.
The Strategy Pattern: A Recipe for Flexibility
Do you like to have options? The Strategy Design Pattern is like having a buffet of options for your code. It allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. The pattern separates the algorithm's implementation from its use, allowing you to modify the algorithm independently of the context in which it is used.
Here's how it works:
Context: This is the class that defines the interface to the client and maintains a reference to a Strategy object.
Strategy: This is the interface that defines the algorithm's behavior.
Concrete Strategy: This is the implementation of the Strategy interface.
In simpler words:
The strategy pattern helps us to identify the aspects of our application that vary and separate them from what stays the same. It allows us to favor composition over inheritance.
For example, let's say we are building a game that simulates different types of Ducks. Each duck has different flying behaviors. This application can be made clean and simple using the Strategy Pattern.
Let's first define the interface FlyBehavior (Strategy):
public interface FlyBehavior{
public void fly();
}
Now we code the specific behaviors (concrete strategy):
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I am flying with wings");
}
}
public class FlyNoWay implements FlyBehavior{
public void fly(){
System.out.println("I can't fly");
}
}
public class FlyWithRockets implements FlyBehavior{
public void fly(){
System.out.println("I am flying with a Rocket");
}
}
Finally, we define the Context class that maintains a reference to a Strategy object:
public class Duck {
private FlyBehavior flyBehavior;
public Duck(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void fly() {
flyBehavior.fly(); //Delegate to the Behavior Class
}
}
Now let's use the context class Duck to set the Fly Behavior dynamically and see the magic of the Strategy Pattern!
Duck rubberDuck = new Duck(new FlyNoWay());
Duck mallardDuck = new Duck(new FlyWithWings());
rubberDuck.fly(); // Output: I can't fly
mallardDuck.fly(); // Output: I am flying with wings
mallardDuck.setFlyBehavior(new FlyWithRockets());
mallardDuck.fly(); // Output: I am flying with a Rocket
As you can see, the Strategy Pattern allows us to switch between different fly behaviors at runtime by setting the fly behavior using the setFlyBehavior method.
But...Why?
After learning this pattern my first reaction was WHY, why would I use it in the first place?
Well, the usage of all the Design Patterns is dependent on the scale of our applications. In the above case, we could just use Inheritance and would have gotten over it as well. But if our application demands a large number of behaviors that have to be changed on runtime, Strategy Pattern would seem the easiest and the most feasible way.

