The Strategy Pattern

Site Admin · 11 Sep 2026 · 9 views

The Strategy Pattern

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime. Instead of hard-coding a single algorithm inside a class, you pass in the algorithm as a strategy object. The context delegates work to the strategy, and you can swap strategies without touching the context code.

Why Strategy Matters

Imagine a shopping cart that needs to support multiple payment methods: credit card, PayPal, and crypto. Without Strategy you would end up with messy conditionals inside pay(). With Strategy each payment method becomes its own class, the cart just calls strategy.pay(amount), and adding a new method means writing one new class - not modifying existing logic.

Class Diagram

    +--------------------+
    |    PaymentContext   |
    +--------------------+
    | - strategy:        |
    |   PaymentStrategy  |
    +--------------------+
    | + setStrategy(s)   |
    | + pay(amount)      |
    +---------+----------+
              |
              | uses
              v
    +--------------------+
    |  PaymentStrategy   |  <<interface>>
    +--------------------+
    | + pay(amount)      |
    +---------+----------+
              |
   +----------+----------+-------------+
   |          |          |             |
+--+-------+ +--+-----+ +--+--------+
| Credit   | |PayPal  | | Crypto    |
| Card     | |        | |           |
+----------+ +--------+ +-----------+

Code Example

Define the strategy interface and three concrete strategies:

public interface PaymentStrategy {
    void pay(int amount);
}

public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    public CreditCardPayment(String cardNumber) {
        this.cardNumber = cardNumber;
    }
    public void pay(int amount) {
        System.out.println("Paid " + amount + " with card " + cardNumber);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;
    public PayPalPayment(String email) { this.email = email; }
    public void pay(int amount) {
        System.out.println("Paid " + amount + " via PayPal: " + email);
    }
}

The context holds a strategy reference and delegates payment. Notice how clean the context is - it knows nothing about how payment actually works:

public class ShoppingCart {
    private PaymentStrategy strategy;
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    public void checkout(int amount) {
        strategy.pay(amount);
    }
}

// Usage
ShoppingCart cart = new ShoppingCart();
cart.setStrategy(new CreditCardPayment("4111-1111-1111"));
cart.checkout(500);
cart.setStrategy(new PayPalPayment("user@example.com"));
cart.checkout(300);

Favour Composition Over Inheritance

Strategy embodies the principle of composition over inheritance. Instead of creating subclasses like CreditCardCart and PayPalCart, you compose the cart with different strategy objects. This keeps the class hierarchy flat and makes runtime changes trivial.

Real-World Use

Sorting is a classic example. Java allows you to pass a Comparator to Collections.sort(). Each comparator is a different sorting strategy. You can sort by name, date, or price simply by swapping the comparator - no need to modify the sort algorithm itself.

Key Points

  • Strategy decouples algorithm selection from the context that uses the algorithm.
  • New algorithms can be added without modifying existing classes (Open-Closed Principle).
  • Favour composition over inheritance - strategies are composed into the context object.
  • Eliminates long conditional chains and switch statements.
  • Each strategy class should have a single responsibility.
Share this post:

Comments (0)

Please login or register to comment.