The Strategy pattern allows you to define a family of interchangeable algorithms and encapsulate each one into a separate class. The pattern enables the algorithms to be selected at runtime based on the context or client's requirements.
// Strategy Interface
interface AccelerationStrategy {
void accelerate();
}
// Concrete Strategy
class NormalAccelerationStrategy implements AccelerationStrategy {
@Override
public void accelerate() {
System.out.println("Vehicle is accelerating at a normal pace.");
}
}
// Concrete Strategy
class SportsAccelerationStrategy implements AccelerationStrategy {
@Override
public void accelerate() {
System.out.println("Vehicle is accelerating aggressively!");
}
}
// Concrete Strategy
class EconomicAccelerationStrategy implements AccelerationStrategy {
@Override
public void accelerate() {
System.out.println("Vehicle is accelerating slowly and conserving fuel.");
}
}
// Context
class Vehicle {
private AccelerationStrategy accelerationStrategy;
public void setAccelerationStrategy(AccelerationStrategy accelerationStrategy) {
this.accelerationStrategy = accelerationStrategy;
}
public void accelerate() {
accelerationStrategy.accelerate();
}
}
// Main class
public class Main {
public static void main(String[] args) {
// Create a vehicle
Vehicle vehicle = new Vehicle();
// Set normal acceleration strategy
vehicle.setAccelerationStrategy(new NormalAccelerationStrategy());
vehicle.accelerate(); // Output: Vehicle is accelerating at a normal pace.
// Set sports car acceleration strategy
vehicle.setAccelerationStrategy(new SportsAccelerationStrategy());
vehicle.accelerate(); // Output: Vehicle is accelerating aggressively!
// Set economic acceleration strategy
vehicle.setAccelerationStrategy(new EconomicAccelerationStrategy());
vehicle.accelerate(); // Output: Vehicle is accelerating slowly and conserving fuel.
}
}
In this example, The Vehicle
class represents a vehicle and has a accelerationStrategy
field of type AccelerationStrategy
. This field holds the currently selected strategy for acceleration. The Vehicle
class also has a setAccelerationStrategy()
method that allows setting a new acceleration strategy at runtime.
The AccelerationStrategy
interface defines the contract for all concrete acceleration strategies. It has a single method called accelerate()
, which encapsulates the algorithm for accelerating the vehicle. There are three concrete implementations of AccelerationStrategy
, which are NormalAccelerationStrategy
, SportsAccelerationStrategy
, EconomicAccelerationStrategy
.
The Main
class demonstrates the usage of the Strategy pattern. It creates an instance of the Vehicle
class and sets different acceleration strategies. It then calls the accelerate()
method, which delegates the behavior to the currently set acceleration strategy.
By using the Strategy pattern, the Vehicle
class can easily switch between different acceleration strategies without tightly coupling to any specific strategy implementation. This allows for greater flexibility and extensibility, as new strategies can be added without modifying the Vehicle
class itself.
Use the Strategy when you have a lot of similar classes that only differ in the way they execute some behavior.
- In the example provided, the
Vehicle
class encapsulates the core behavior related to acceleration. The different acceleration strategies (EconomicAccelerationStrategy
,NormalAccelerationStrategy
andSportsAccelerationStrategy
) represent the algorithms for achieving acceleration in specific contexts. By using the Strategy pattern, the Vehicle class can switch between different strategies without affecting its core implementation, promoting a flexible and modular design.
Use the pattern to isolate the business logic of a class from the implementation details of algorithms that may not be as important in the context of that logic.
Use the pattern when your class has a massive conditional operator that switches between different variants of the same algorithm.