xIntroduction

Imagine you are building an e-commerce application.

A customer wants to make a payment.

The application supports multiple payment methods:

  • Credit Card

  • UPI

  • PayPal

  • Net Banking

  • Wallet

A beginner might write something like this:


This works initially.

But what happens when new payment methods are added?

  • Apple Pay

  • Google Pay

  • Crypto

  • EMI

The conditional statements keep growing.

The code becomes:

  • Hard to maintain

  • Hard to extend

  • Difficult to test

This is where the Strategy Design Pattern helps.

Instead of placing all algorithms inside one class, the Strategy pattern moves each algorithm into a separate class and allows them to be selected dynamically at runtime.

What is the Strategy Pattern?

The Strategy Pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one, and makes them interchangeable.

In simple words:

The Strategy Pattern allows you to change an object's behavior by switching the algorithm it uses.

The client can choose which strategy to use without modifying existing code.

Real World Analogy

Consider Google Maps.

When you enter a destination, you can choose:

  • Driving Route

  • Walking Route

  • Cycling Route

  • Public Transport Route

The destination remains the same.

Only the route calculation algorithm changes.

Each route calculation method represents a different strategy.

Google Maps simply switches between strategies based on user choice.

Why Do We Need the Strategy Pattern?

Suppose we are building a payment system.

Without the Strategy Pattern:


At first, this looks fine.

But several problems appear as the system grows.

Problems Without Strategy Pattern

1. Large Conditional Statements

The number of if-else blocks keeps increasing.

if(...)
else if(...)
else if(...)
else if(...) 

The code becomes difficult to read.

2. Violates the Open-Closed Principle

Adding a new payment method requires modifying existing code.

3. Difficult to Test

Each algorithm lives inside one large class.

Testing individual payment methods becomes harder.

4. Poor Maintainability

Changes in one algorithm may accidentally affect others.

Solution: Strategy Pattern

The Strategy Pattern solves this problem by separating each algorithm into its own class.

Instead of:

if(paymentType == ...)

We create:

CardPaymentStrategy
UPIPaymentStrategy
PayPalPaymentStrategy

The application simply chooses which strategy to use.

Structure of Strategy Pattern

The Strategy Pattern typically contains:

1. Strategy Interface

Defines a common contract for all algorithms.

2. Concrete Strategies

Individual algorithm implementations.

3. Context

Uses a strategy object to perform work.

4. Client

Chooses which strategy should be used.

Strategy Pattern Structure

            Strategy
                ▲
                │
     -------------------------
     │           │          │
 CardStrategy  UPIStrategy PayPalStrategy

                ▲
                │
             Context

Example: Payment System

Let's implement a payment system using the Strategy Pattern.

Step 1: Create Strategy Interface


Step 2: Create Concrete Strategies

Card Payment Strategy:


UPI Payment Strategy:


PayPal Payment Strategy:


Step 3: Create Context


Step 4: Client Code


Output

Paid 500 using UPI

Paid 1000 using Credit Card

How the Strategy Pattern Works

Let's understand the complete flow.

Step 1

Client chooses a strategy.

new UPIPaymentStrategy()

Step 2

The strategy is injected into the context.

PaymentProcessor(strategy)

Step 3

The context delegates the work.

strategy->pay(amount);

Step 4

The selected algorithm executes.

UPIPaymentStrategy::pay()

Key Idea Behind Strategy Pattern

The most important idea is:

Encapsulate algorithms and make them interchangeable.

The context does not care which algorithm is being used.

It only knows:

PaymentStrategy

This reduces coupling and improves flexibility.

Runtime Strategy Switching

One of the biggest advantages of this pattern is runtime switching.

Example:


Now the behavior changes without modifying existing code.

This is impossible with large if-else blocks.

Strategy vs Inheritance

A common beginner approach is:

CardPaymentProcessor
UPIPaymentProcessor
PayPalPaymentProcessor

This leads to excessive inheritance.

Strategy uses composition instead.

PaymentProcessor
        |
        ▼
 PaymentStrategy

Composition is generally more flexible than inheritance.

Strategy vs Observer

This is a common interview question.

Strategy PatternObserver Pattern
Changes behaviorSends notifications
Focuses on algorithmsFocuses on communication
One strategy active at a timeMultiple observers can exist
Client chooses strategySubject notifies observers

Advantages of Strategy Pattern

1. Eliminates Large Conditionals

No need for huge if-else chains.

2. Easy to Extend

Adding a new algorithm only requires creating a new strategy.

Example:

CryptoPaymentStrategy

3. Supports the Open-Closed Principle

Existing code remains unchanged.

4. Improves Testing

Each strategy can be tested independently.

5. Runtime Flexibility

Algorithms can be switched dynamically.

6. Better Separation of Concerns

Each strategy has a single responsibility.

Disadvantages of the Strategy Pattern

1. More Classes

Each algorithm requires a separate class.

2. Client Must Understand Strategies

The client needs to know which strategy to choose.

3. Slightly Increased Complexity

For very simple systems, Strategy may be unnecessary.

Real World Applications

The Strategy Pattern is widely used in:

  • Payment gateways

  • Route planning systems

  • Sorting algorithms

  • Compression utilities

  • Authentication mechanisms

  • Tax calculation systems

  • Pricing engines

  • Recommendation systems

  • Game AI behavior systems

Many modern frameworks internally use Strategy Pattern concepts.

Common Beginner Mistakes

1. Using Strategy for Small Logic

Not every if-else needs a Strategy Pattern.

Use it when algorithms are likely to grow.

2. Mixing Multiple Responsibilities

Each strategy should focus on one algorithm only.

3. Using Inheritance Instead of Composition

Strategy is built around composition.

Avoid creating large inheritance hierarchies.

4. Creating Too Many Tiny Strategies

Only separate logic when meaningful algorithm variations exist.

Simple Visualization

Without Strategy:

Context

 ├── if(Card)
 ├── if(UPI)
 ├── if(PayPal)
 └── if(Wallet)

With Strategy:

Context
    │
    ▼
Strategy Interface
    ▲
    │
 ┌───────┬────────┬─────────┐
 │       │        │         │
Card    UPI    PayPal    Wallet

The context delegates behavior instead of implementing every algorithm itself.

Summary

The Strategy Design Pattern allows multiple algorithms to be encapsulated into separate classes and selected dynamically at runtime.

Instead of relying on large conditional statements, the context delegates work to a strategy object that implements a common interface.

This leads to cleaner, more maintainable, and more extensible code while supporting runtime behavior changes without modifying existing business logic.

Whenever you find yourself writing long chains of if-else statements to choose between different algorithms, the Strategy Pattern is often an excellent design choice.