Behavioral Pattern

Strategy Pattern

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

12 min readHigh Priority

1What is Strategy Pattern?

Real-World Analogy
Navigation App

Google Maps lets you choose between driving, walking, cycling, or public transit. Each is a different "strategy" to reach your destination. The app doesn't care which you pick - it just executes the chosen strategy.

Payment Options

An e-commerce site accepts credit card, PayPal, UPI, or crypto. Each payment method is a strategy. The checkout process remains the same, but the actual payment logic varies based on your choice.

Strategy is a behavioral pattern that lets you define a family of algorithms, put each into a separate class, and make their objects interchangeable. It enables selecting an algorithm at runtime.

Strategy Pattern Structure

Context- strategy: Strategy<<interface>>Strategy+ execute()ConcreteStrategyAConcreteStrategyBConcreteStrategyC
Context delegates work to Strategy. Concrete strategies implement the algorithm.

2Problem It Solves

Without Strategy, you end up with massive conditional statements:

Without Strategy
public void pay(String type) {
  if (type.equals("CREDIT")) {
    // Credit card logic
  } else if (type.equals("PAYPAL")) {
    // PayPal logic  
  } else if (type.equals("UPI")) {
    // UPI logic
  } else if (type.equals("CRYPTO")) {
    // Crypto logic
  }
  // Adding new method = modify this
}
  • - Violates Open/Closed
  • - Hard to test
  • - Tight coupling
With Strategy
public void pay(PaymentStrategy s) {
  s.pay(amount);
  // That's it!
}

// Each strategy is a separate class
// Adding new method = add new class
// No modification to existing code
  • + Open for extension
  • + Easy to test
  • + Loose coupling

3Implementation

Strategy Pattern - Payment Processing
// ========== Strategy Interface ==========
interface PaymentStrategy {
    void pay(double amount);
    boolean validate();
}

// ========== Concrete Strategies ==========
class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    private String cvv;
    
    public CreditCardPayment(String cardNumber, String cvv) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }
    
    @Override
    public boolean validate() {
        return cardNumber.length() == 16 && cvv.length() == 3;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Paid $" + amount + " using Credit Card");
    }
}

class PayPalPayment implements PaymentStrategy {
    private String email;
    
    public PayPalPayment(String email) {
        this.email = email;
    }
    
    @Override
    public boolean validate() {
        return email.contains("@");
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Paid $" + amount + " using PayPal: " + email);
    }
}

class UPIPayment implements PaymentStrategy {
    private String upiId;
    
    public UPIPayment(String upiId) {
        this.upiId = upiId;
    }
    
    @Override
    public boolean validate() {
        return upiId.contains("@");
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Paid $" + amount + " using UPI: " + upiId);
    }
}

// ========== Context ==========
class ShoppingCart {
    private List<Item> items = new ArrayList<>();
    private PaymentStrategy paymentStrategy;
    
    public void addItem(Item item) {
        items.add(item);
    }
    
    public double calculateTotal() {
        return items.stream().mapToDouble(Item::getPrice).sum();
    }
    
    // Strategy can be set/changed at runtime
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout() {
        double total = calculateTotal();
        if (paymentStrategy.validate()) {
            paymentStrategy.pay(total);
        } else {
            System.out.println("Payment validation failed");
        }
    }
}

// ========== Usage ==========
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(new Item("Laptop", 999.99));
        cart.addItem(new Item("Mouse", 29.99));
        
        // Pay with Credit Card
        cart.setPaymentStrategy(new CreditCardPayment("1234567890123456", "123"));
        cart.checkout();
        
        // Same cart, different payment method
        cart.setPaymentStrategy(new PayPalPayment("user@email.com"));
        cart.checkout();
        
        // Or UPI
        cart.setPaymentStrategy(new UPIPayment("user@okbank"));
        cart.checkout();
    }
}
Output:
Paid $1029.98 using Credit Card
Paid $1029.98 using PayPal: user@email.com
Paid $1029.98 using UPI: user@okbank

4Real-World Applications

Sorting Algorithms
Collections.sort(list, comparator)
Java's Comparator is a strategy for comparing objects. You can swap between different comparison strategies.
Compression
ZIP, GZIP, LZ4, etc.
File archivers let you choose compression algorithms. Each is a strategy with different speed/ratio tradeoffs.
Validation Rules
Form validators
Different validation strategies: email, phone, password strength. Same form, different validators.
Caching Strategies
LRU, LFU, FIFO
Cache eviction policies are strategies. You can swap them without changing the cache implementation.

5Strategy vs State Pattern

These patterns look similar but solve different problems:

AspectStrategyState
PurposeChoose algorithmManage state transitions
Who decides?Client sets strategyState changes itself
AwarenessStrategies don't know each otherStates know about transitions
ExamplePayment methodsOrder status (pending → shipped → delivered)

6Interview Follow-up Questions

Interview Follow-up Questions

Common follow-up questions interviewers ask

7Key Takeaways

1Strategy encapsulates algorithms in separate classes.
2Algorithms are interchangeable at runtime.
3Follows Open/Closed Principle - extend without modifying.
4Use when: multiple algorithms, runtime selection needed.
5Different from State: client chooses vs object decides.
6Examples: payment methods, sorting, compression, validation.