Back to Design Patterns
Behavioral Design Pattern

Strategy Pattern

Don't hardcode your algorithms. Encapsulate them into interchangeable components and switch them at runtime to build truly flexible and scalable software.

Level: IntermediateTime: 20 minSOLID Compliant

The "God Method" Problem

In traditional programming, you often end up with a single class that needs to handle multiple variations of a task. This leads to a massive, fragile switch or if-else block.

Every time you want to add a new algorithm, you must modify that class, risking the breakage of existing code. This violates the Open/Closed Principle.

Anti-Pattern (Tangled Code)
function calculate(type, data) {
  if (type === 'fast') {
    // 50 lines of logic
  } else if (type === 'cheap') {
    // 50 lines of logic
  } else if (type === 'secure') {
    // 50 lines of logic
  }
  // This grows forever...
}

Architectural Components

The Context

The object that needs to perform a task but doesn't care about the details of the algorithm.

The Interface

The contract that all strategies must follow. It ensures the Context can talk to any strategy.

Concrete Strategies

Multiple classes that implement the interface with specific, unique logic for the task.

Tutorial: Step-by-Step

Master the implementation across different environments.

/**
 * ADVANCED JAVA IMPLEMENTATION
 * Using Strategy with Dependency Injection concepts
 */

// 1. The Strategy Interface
interface RouteStrategy {
    String calculateRoute(String A, String B);
    int getEstimatedTime();
}

// 2. Concrete Strategy: Driving
class RoadStrategy implements RouteStrategy {
    public String calculateRoute(String A, String B) {
        return "Calculating fastest road route from " + A + " to " + B;
    }
    public int getEstimatedTime() { return 30; }
}

// 3. Concrete Strategy: Walking
class WalkingStrategy implements RouteStrategy {
    public String calculateRoute(String A, String B) {
        return "Finding scenic walking paths from " + A + " to " + B;
    }
    public int getEstimatedTime() { return 120; }
}

// 4. Concrete Strategy: Public Transit
class TransitStrategy implements RouteStrategy {
    public String calculateRoute(String A, String B) {
        return "Checking bus and train schedules between " + A + " and " + B;
    }
    public int getEstimatedTime() { return 45; }
}

// 5. The Context Class
class Navigator {
    private RouteStrategy strategy;

    // Default strategy set via constructor
    public Navigator(RouteStrategy strategy) {
        this.strategy = strategy;
    }

    // Dynamic strategy switching (Runtime)
    public void setStrategy(RouteStrategy strategy) {
        this.strategy = strategy;
    }

    public void buildRoute(String start, String end) {
        System.out.println("--- Navigation Report ---");
        System.out.println(strategy.calculateRoute(start, end));
        System.out.println("ETA: " + strategy.getEstimatedTime() + " minutes");
    }
}

// 6. Usage
public class StrategyDemo {
    public static void main(String[] args) {
        Navigator googleMaps = new Navigator(new RoadStrategy());
        googleMaps.buildRoute("New York", "Boston");

        // User decides to walk instead
        googleMaps.setStrategy(new WalkingStrategy());
        googleMaps.buildRoute("Central Park", "Times Square");
    }
}

Pro Tip: Functional JS

In JavaScript, you don't always need classes. Passing a function as an argument is a literal implementation of the Strategy Pattern!

Runtime Injection

Combine this pattern with a Factory to decide which strategy to load based on a configuration file or database setting.

When to Reach for Strategy

Algorithmic Variations

When you have many versions of the same behavior (e.g., different compression types, sorting algorithms, or encryption methods).

Isolating Complexity

When an algorithm uses data that the business logic shouldn't know about. Strategy hides that data inside the strategy classes.

Avoiding Conditional Bloat

If your code is drowning in if (type == X), Strategy is your life raft to clean, modular logic.

Strategic Analysis

The Benefits

  • Eliminate massive conditional logic.
  • Algorithms are decoupled from the client code.
  • New algorithms can be added without touching existing ones.
  • Switch behaviors at runtime (hot-swapping).
  • Enables better unit testing of individual algorithms.

The Drawbacks

  • Increases the number of objects/classes in the system.
  • Clients must understand the differences between strategies.
  • Communication overhead between Context and Strategy.
  • Functional languages can often do this simpler with closures.

Strategy vs. Template Method

PatternMechanismFlexibility
StrategyComposition (Has-A)High: Change behavior at runtime.
TemplateInheritance (Is-A)Medium: Locked in at compile time.

Challenge Yourself

Try implementing a File Compression System using the Strategy pattern where the user can choose between ZIP, GZIP, and RAR formats at runtime!