This content originally appeared on DEV Community and was authored by Heli Shah
Design patterns are essential tools in a software engineer’s toolkit. They help solve common problems with proven solutions. Among the behavioral patterns, the Strategy Design Pattern stands out for its flexibility and ability to keep code clean and maintainable. In this blog post, we’ll explore the Strategy Pattern, understand when to use it, and see a practical implementation in Java.
What is the Strategy Pattern?
The Strategy Pattern allows you to define a family of algorithms, encapsulate each one as a separate class, and make them interchangeable. Instead of hardcoding a behavior into a class, the behavior is pulled out and placed into separate strategy classes.
Category: Behavioral Design Pattern
Purpose: Select an algorithm’s behavior at runtime.
When to Use the Strategy Pattern
You should consider using the Strategy Pattern when:
- You have multiple related algorithms that vary only in behavior.
- You need to switch algorithms at runtime.
- You want to avoid multiple conditional statements like
if
orswitch
. - You want to adhere to the Open/Closed Principle (open for extension, closed for modification).
Real-World Analogy
Think of a navigation app. You can choose between different strategies to reach your destination:
- Fastest Route
- Shortest Distance
- Avoid Tolls
Each of these is a different strategy for solving the same problem: navigation. The app lets you pick the strategy dynamically.
Structure of the Strategy Pattern
- Strategy Interface: Common interface for all strategies.
- Concrete Strategies: Implement the interface with specific behaviors.
- Context: Maintains a reference to the strategy and delegates the behavior.
Java Implementation: Payment System
Let’s implement a payment system where the user can choose how to pay: via Credit Card, PayPal, or UPI.
1. Strategy Interface
public interface PaymentStrategy {
void pay(double amount);
}
2. Concrete Strategies
public class CreditCardPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid ₹" + amount + " using Credit Card");
}
}
public class PayPalPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid ₹" + amount + " using PayPal");
}
}
public class UPIPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid ₹" + amount + " using UPI");
}
}
3. Context Class
public class PaymentProcessor {
private PaymentStrategy strategy;
public PaymentProcessor(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void processPayment(double amount) {
strategy.pay(amount);
}
}
4.Usage
public class StrategyPatternDemo {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor(new CreditCardPayment());
processor.processPayment(2500.00);
processor.setStrategy(new PayPalPayment());
processor.processPayment(1200.00);
processor.setStrategy(new UPIPayment());
processor.processPayment(500.00);
}
}
Output:
Paid ₹2500.0 using Credit Card
Paid ₹1200.0 using PayPal
Paid ₹500.0 using UPI
Benefits of Using Strategy Pattern
- Flexibility: You can change the algorithm at runtime.
-
Clean Code: Avoids long
if-else
orswitch
statements. - Scalability: Easy to add new strategies without touching existing logic.
- Testability: Each strategy can be tested independently.
Final Thoughts
The Strategy Pattern is ideal when you need different variations of an algorithm and want to keep your code modular and maintainable. It embraces composition over inheritance and aligns perfectly with SOLID principles.
Understanding and applying the Strategy Pattern in your Java applications can help you write better-designed, more testable, and maintainable code.
Ready to replace those messy if-else
blocks with elegant strategies? Happy coding!
This content originally appeared on DEV Community and was authored by Heli Shah