🎯 Strategy Design Pattern: Write Flexible & Maintainable Code

🎯 Strategy Design Pattern: Write Flexible & Maintainable Code

In the real world—and in code—the way you do something can vary, but the goal often stays the same.

The Strategy Design Pattern gives you the power to define multiple ways (strategies) to accomplish a task and choose the most appropriate one at runtime. It’s all about writing clean, scalable, and extensible code.


🤔 What Is the Strategy Pattern?

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. This allows the behavior of a class to change without modifying its source code.


🧠 Some Real-World Analogies

📦 Shipping a Package

Think of sending a package. You can choose different shipping strategies:

  • 🚀 Air (fast but expensive)
  • 🚚 Ground (moderate speed and cost)
  • 🚢 Sea (slow but cheap)

The goal is the same (deliver the package), but how you do it varies based on urgency, budget, or distance.

In the Strategy Pattern, each of these shipping methods would be a different strategy class, and the client (you) chooses which one to use.

🧑🍳 Cooking a Meal

You want to cook pasta, but you can choose:

  • 🍝 Boiling (classic)
  • 🍳 Pan-fry (crispy edges)
  • 🥘 Baked (cheesy and crunchy)

Same goal, different methods. The Strategy Pattern is like giving the chef (your app) the freedom to choose the best method based on taste or context.


// Payment-Methods
package LLD.StrategyDesign;

interface PaymentMethod{
    void processPayment();
    String getMethod();
}
class CreditCard  extends implements PaymentMethod{ 
    public CreditCard(){
        // constructor
        System.out.println("Initiating CC");
    }
    public void processPayment(){
        System.out.println("CC payment accepted");
    }
    public String getMethod(){
        return "Credit Card";
    }

    
}
class DebitCard  implements PaymentMethod{ 
    public DebitCard(){
        // constructor
        System.out.println("Initiating DC");
    }
    public void processPayment(){
        System.out.println("DC payment accepted");
    }
    public String getMethod(){
        return "Debit Card";
    }
}
class Cash  implements PaymentMethod{ 
    public Cash(){
        // constructor
        System.out.println("Initiating Cash payment");
    }
    public void processPayment(){
        System.out.println("Cash payment accepted");
    }
    public String getMethod(){
        return "Cash";
    }
}

//Payment-Processor
package LLD.StrategyDesign;

public class PaymentProcessor{
    private PaymentMethod strategy;
    public PaymentProcessor(PaymentMethod user_pay_method){
        // constructor
        this.strategy=user_pay_method;
        System.out.println("Current Payment Method is "+ strategy.getMethod());
    }    
    void process(){
        strategy.processPayment();
    }
    // change payment method in runtime
    void setStrategy(PaymentMethod method){
        this.strategy=method;
    }
}

//Main.java
package LLD.StrategyDesign;

public class Main{
    public static void main(String[] args){
        System.out.println("Hello World from main");
        PaymentMethod cc=new CreditCard();
        PaymentProcessor processor=new PaymentProcessor(cc);
        processor.process();
        PaymentMethod dc=new DebitCard()
        // we can avoid using setStrategy ..and just pass the curr PaymentMethod obj to process and in process implemement the PaymentMethod.process()
        processor.setStrategy(dc);
        processor.process();
    }
}        

💻 Software Development Example

Use Case: Payment Processing

Imagine an e-commerce site that supports multiple payment methods:

  • 💳 Credit Card
  • 💰 Wallet
  • 🪙 UPI
  • 💵 Cash on Delivery

Instead of writing a bunch of if-else conditions, use the Strategy Pattern:

  • Define a PaymentStrategy interface.
  • Implement strategies like CreditCardPayment, WalletPayment, UPIPayment.
  • The client chooses the strategy at runtime based on user input.

🧼 This makes your code modular, clean, and easy to extend—adding a new method like Crypto Payment just means writing a new strategy class!


📱 Some other use cases

  • 🎼 Music Player App: Different playback strategies – shuffle, repeat, or sequential.
  • 🧹 File Cleaner Tool: Strategy for deleting files – by age, size, or type.
  • 🌐 Authentication: Use JWT, OAuth, or API key depending on the use case.
  • 📊 Data Sorting: Use QuickSort, MergeSort, or HeapSort depending on data size and structure.


✅ Why Use the Strategy Pattern?

  • Open/Closed Principle: Add new behavior without touching existing code.
  • Loose Coupling: The client is decoupled from the logic.
  • Testability: Each strategy can be tested independently.
  • Maintainability: Your code is cleaner and easier to manage.


💡 When to use

Use the Strategy Pattern when:

  • You have multiple ways to perform a task.
  • You want to avoid long chains of conditionals.
  • You want to make your code modular and future-proof.


✨ Design smarter. Code cleaner. Build systems that are flexible by design.

#DesignPatterns #StrategyPattern #OOP #CleanCode #SoftwareEngineering #TechTips #Java #Python #SystemDesign #ProgrammingLife #RealWorldTech

To view or add a comment, sign in

More articles by Samartha Khare

Explore content categories