The Strategy Pattern defines a family of algorithms, encapsulates each one into its own class, and makes them interchangeable at runtime. Instead of hardcoding behaviors into an object's DNA via inheritance, you give the object a "slot" and plug the behavior in via composition.
FlyingAndSqueakingDuck or NonFlyingAndMuteDuck).RouteStrategy from driving to walking without reloading the map).
The image illustrates the architecture perfectly by splitting the behaviors into modular trees. FlyBehavior is an interface that all flying classes implement, meaning new flying classes just need to implement the fly() method. Similarly, QuackBehavior is an interface that just includes a quack() method that needs to be implemented.
1. Define the Interfaces
public interface FlyBehavior{
void fly();
}
public interface QuackBehavior{
void quack();
}
2. Create Concrete Strategies
As shown in the diagram, FlyWithWings implements duck flying, while FlyNoWay provides the implementation for ducks that can't fly by doing nothing. The quack behaviors are split into Quack (quacks that really quack), Squeak (quacks that squeak, like a rubber duckie), and MuteQuack (quacks that make no sound at all).
public class FlyWithWings implements FlyBehavior{
public void fly(){ System.out.println("Flying!"); }
}
public class FlyNoWay implements FlyBehavior{
public void fly(){ // do nothing - can't fly!
}
}
3. Build the Base Class (The Delegator)
The base class holds the interfaces, not the concrete classes.
public abstract class Duck{
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public void performFly(){ this.flyBehavior.fly(); }
// Allows swapping at runtime
public void setFlyBehavior(FlyBehavior fb){ this.flyBehavior = fb; }
}
4. Build the Client
The concrete duck wires up its initial state in the constructor.