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

Instead of embedding multiple algorithms inside a single class using conditional statements, each algorithm is implemented as a separate strategy class. The client selects the appropriate strategy based on its requirements.

This approach follows the Open/Closed Principle by allowing new algorithms to be introduced without modifying existing code.

The Strategy Pattern is commonly used for payment processing, sorting algorithms, discount calculation, compression algorithms, and authentication mechanisms.

Structure

The Strategy Pattern consists of the following participants.

1. The Strategy defines the common interface for all algorithms.
2. Concrete Strategies implement different versions of the algorithm.
3. The Context maintains a reference to a strategy object and delegates work to it.
4. The Client selects the appropriate strategy and configures the context.

Java Implementation

Suppose an e-commerce application supports multiple payment methods. Depending on the user's choice, the application should process the payment using Credit Card, PayPal, or UPI without changing the checkout logic.

Create the strategy interface.
public interface PaymentStrategy {
    void pay(double amount);
}
Create the concrete strategies.
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid using Credit Card: " + amount);
    }
}
public class PaypalPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid using PayPal: " + amount);
    }
}
public class UpiPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid using UPI: " + amount);
    }
}
Create the context.
public class PaymentService {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public void checkout(double amount) {
        paymentStrategy.pay(amount);
    }
}
The client selects the required payment strategy.
public class Main {
    public static void main(String[] args) {
        PaymentService service = new PaymentService();
        service.setPaymentStrategy(new UpiPayment());
        service.checkout(2500);
    }
}
Output:
Paid using UPI: 2500.0

How It Works?

The client creates a PaymentService object, which acts as the context responsible for processing payments.

Instead of implementing the payment logic itself, the context delegates the operation to a PaymentStrategy object.

The client chooses the desired strategy, such as CreditCardPayment, PaypalPayment, or UpiPayment, and injects it into the context.

When the checkout() method is called, the context invokes the strategy's pay() method without knowing which concrete implementation is being used.

This allows payment methods to be switched dynamically at runtime without modifying the checkout logic or introducing complex conditional statements.

Advantages

1. It eliminates large conditional statements by encapsulating algorithms into separate classes.
2. Algorithms can be selected and changed at runtime.
3. New strategies can be added without modifying existing code.
4. It promotes loose coupling between the context and algorithm implementations.

Disadvantages

1. The pattern introduces additional strategy classes.
2. Clients must know which strategy is appropriate for a given situation.
3. Managing many strategies may increase application complexity.

JDK Examples

The Strategy Pattern appears throughout the Java ecosystem.

1. The java.util.Comparator interface allows different comparison strategies to be supplied to sorting methods such as Collections.sort() and List.sort().

2. The java.util.concurrent.RejectedExecutionHandler interface defines different strategies for handling tasks that cannot be executed by a thread pool.

Summary

The Strategy Pattern encapsulates multiple algorithms as separate objects and allows them to be selected interchangeably at runtime.

By separating algorithms from the objects that use them, the pattern improves flexibility, simplifies maintenance, and makes applications easier to extend with new behaviours.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer • Java • Python • Distributed Systems • AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

💬 Comments

Join the Discussion