Strategy Pattern belongs to the Behavioral category of design patterns.
Why? Because it’s all about how objects interact and behave. Strategy focuses on choosing behavior dynamically at runtime, like swapping brains for specific tasks.
In today’s fast paced world of e-commerce and quick-commerce, you’ve likely had that classic cart checkout moment, staring at a bunch of coupon codes, trying to pick the one that saves you the most money.
If yes, congratulations! You’ve already seen the Strategy Pattern in real life.
The Shopping Cart Coupon Chaos
Let’s say you’re building your very own e-commerce app and want to support multiple coupon types,
"FLAT200" → ₹200 off
"NEWUSER" → 20% off
"FESTIVE" → ₹100 + free delivery
"BUYMORE" → 15% off above ₹1000
Your code might start like this,
Function ApplyCoupon(cartAmount, couponCode)
If couponCode == "FLAT200"
Return cartAmount - 200
Else if couponCode == "NEWUSER"
Return cartAmount * 0.8
Else if couponCode == "FESTIVE"
Return cartAmount - 100 // free delivery handled elsewhere
Else if couponCode == "BUYMORE" AND cartAmount > 1000
Return cartAmount * 0.85
Else
Return cartAmount
This works. Until, we encounter some challenges/bottlenecks like,
- 2 more coupons get added next week
- You need to test different coupon logics
- Marketing decides to change all rules before the sale ends
- Someone adds one
else if
with a wrong condition and there is a disaster
Enter the Strategy Pattern
It’s like hiring a dedicated coupon brain for each discount logic.
You separate the behavior (how to apply discount) from the decision (which one to use). This is now definitely clean, pluggable and testable.
What does the code look like?
// Step 1: Define Strategy Interface
Interface DiscountStrategy
Method Apply(cart)
// Step 2: Implement each strategy
Class PercentageDiscountStrategy Implements DiscountStrategy
Method Apply(cart)
Return cart.total * 0.9 // 10% off
Class FreeShippingStrategy Implements DiscountStrategy
Method Apply(cart)
Return cart.total - cart.shippingFee
Class FlatDiscountStrategy Implements DiscountStrategy
Method Apply(cart)
Return cart.total - 100
// Mix it up with a Factory pattern 😎
// Step 3: Strategy Factory
Class DiscountStrategyFactory
Static Method GetStrategy(couponCode)
strategyName = DB.GetStrategyClassFor(couponCode)
If strategyName == "PercentageDiscountStrategy"
Return new PercentageDiscountStrategy()
Else if strategyName == "FreeShippingStrategy"
Return new FreeShippingStrategy()
Else if strategyName == "FlatDiscountStrategy"
Return new FlatDiscountStrategy()
Else
Return new NoDiscountStrategy()
// caller logic
Function ApplyCoupon(cart, couponCode)
strategy = DiscountStrategyFactory.GetStrategy(couponCode)
finalAmount = strategy.Apply(cart)
Return finalAmount
Did you notice something familiar in the code?
We’re using a Factory Pattern
to decide which discount strategy to use, based on some configuration stored in DB or elsewhere. With this, we get rid of the messy if-else
branching scattered across the main logic. It is now one centralized place that handles object creation based on input. This is one way of combining multiple design patterns together to make the actual business logic stay clean and decoupled.
💡 If you're not sure what Factory Pattern is or how it works, check out Part 1 of this series.
Why Use Strategy Pattern?
- Business logic keeps changing
- No more branching in core code
- Plug-and-play behavior at runtime
- Add new rules without touching old ones (Open-Closed Principle)
- Easily unit test each discount logic separately
Use Cases?
- Coupon logic
- Payment gateways
- Sorting algorithms
- UI themes
- Game player behavior
- Pricing strategies
- Tax calculation logic
To summarize, it would be apt to say,
Strategy Pattern is a design pattern that lets you define a family of algorithms (strategies), encapsulate them in separate classes, and switch them at runtime.
Code stays clean, changes become easy, and logic becomes testable.
Hope this gave you a clean and fun grasp of the Strategy Design Pattern.
Next up in the series, Observer Pattern.
Top comments (0)