The Strategy pattern is a behavioral design pattern that enables selecting an algorithm or strategy at runtime. It defines a family of algorithms, encapsulates each algorithm, and makes them interchangeable. This pattern allows the algorithm to vary independently from clients that use it.

Key Characteristics:

  • Encapsulation of Algorithms: Each algorithm or strategy is encapsulated within its own class.
  • Interchangeability: Strategies can be swapped easily without modifying the context that uses them.
  • Decoupling: Separates the algorithm from the context that uses it, promoting flexibility and maintainability.

How It Works:

  • Strategy Interface: Defines a common interface for all supported algorithms or strategies.
  • Concrete Strategies: Implement the strategy interface and provide specific algorithm implementations.
  • Context: Uses a strategy object to perform a particular task. It delegates the algorithmic work to the strategy object.

Example in PHP:

  // Strategy Interface
interface Strategy {
    public function execute($a, $b);
}

// Concrete Strategy A
class ConcreteStrategyAdd implements Strategy {
    public function execute($a, $b) {
        return $a + $b;
    }
}

// Concrete Strategy B
class ConcreteStrategySubtract implements Strategy {
    public function execute($a, $b) {
        return $a - $b;
    }
}

// Context
class Context {
    private $strategy;

    public function __construct(Strategy $strategy) {
        $this->strategy = $strategy;
    }

    public function setStrategy(Strategy $strategy) {
        $this->strategy = $strategy;
    }

    public function executeStrategy($a, $b) {
        return $this->strategy->execute($a, $b);
    }
}

// Client Code
$context = new Context(new ConcreteStrategyAdd());
echo "Addition: " . $context->executeStrategy(5, 3) . "\n"; // Output: Addition: 8

$context->setStrategy(new ConcreteStrategySubtract());
echo "Subtraction: " . $context->executeStrategy(5, 3) . "\n"; // Output: Subtraction: 2
  

Explanation:

  1. Strategy Interface: Strategy defines the execute() method that concrete strategies must implement.
  2. Concrete Strategies: ConcreteStrategyAdd and ConcreteStrategySubtract implement the Strategy interface, providing specific algorithm implementations for addition and subtraction.
  3. Context: Context uses a strategy object to perform operations. It delegates the work to the current strategy object.

Benefits:

  • Flexibility: Allows changing the algorithm at runtime without altering the context.
  • Separation of Concerns: Separates algorithm implementation from the context that uses it, promoting cleaner and more maintainable code.
  • Extendibility: New algorithms can be added without modifying the existing code, adhering to the Open/Closed Principle.

Use Cases:

  • Algorithm Selection: When an application needs to support multiple algorithms for a task and allows changing them at runtime.
  • Strategy Variability: For cases where different strategies need to be applied based on varying conditions or user preferences.
  • Policy Implementation: Implementing different policies or behaviors that can be swapped dynamically.

The Strategy pattern is valuable for scenarios where algorithms or behaviors need to be chosen dynamically, and it promotes flexibility, maintainability, and separation of concerns by encapsulating algorithms within their own classes.