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 Pattern | Observer Pattern |
|---|---|
| Changes behavior | Sends notifications |
| Focuses on algorithms | Focuses on communication |
| One strategy active at a time | Multiple observers can exist |
| Client chooses strategy | Subject 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.