Strategy Design Pattern in Java

1. Definition

The Strategy Design Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It allows the algorithm to vary independently from the clients that use it.

2. Problem Statement

How can we design a system to be adaptable to changing algorithms, without having to modify existing code, and without exposing the algorithm's logic to the client?

3. Solution

By defining a family of algorithms and encapsulating each one in a separate class, we can switch between algorithms dynamically. The client interacts with a context that delegates the responsibility of executing the algorithm to the strategy object.

4. Real-World Use Cases

1. Different compression algorithms for file storage.

2. Various sorting algorithms depending on the type and size of data.

3. Payment methods in an e-commerce application (credit card, PayPal, etc.).

5. Implementation Steps

1. Define a strategy interface for the family of algorithms.

2. Implement concrete classes for each algorithm by implementing the strategy interface.

3. Create a context class that uses the strategy interface to execute the algorithm.

6. Implementation

// Strategy interface
interface PaymentStrategy {
    void pay(int amount);
}

// Concrete strategy
class CreditCardStrategy implements PaymentStrategy {
    private String cardNumber;
    public CreditCardStrategy(String cardNumber) {
        this.cardNumber = cardNumber;
    }

    @Override
    public void pay(int amount) {
        System.out.println("Paid using credit card. Amount: " + amount);
    }
}

// Concrete strategy
class PayPalStrategy implements PaymentStrategy {
    private String email;
    public PayPalStrategy(String email) {
        this.email = email;
    }

    @Override
    public void pay(int amount) {
        System.out.println("Paid using PayPal. Amount: " + amount);
    }
}

// Context
class ShoppingCart {
    private PaymentStrategy paymentMethod;

    public ShoppingCart(PaymentStrategy paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public void checkout(int amount) {
        paymentMethod.pay(amount);
    }
}

// Client
public class StrategyPatternDemo {
    public static void main(String[] args) {
        ShoppingCart cart1 = new ShoppingCart(new CreditCardStrategy("1234-5678-9876-5432"));
        cart1.checkout(250);

        ShoppingCart cart2 = new ShoppingCart(new PayPalStrategy("user@example.com"));
        cart2.checkout(300);
    }
}

Output:

Paid using credit card. Amount: 250
Paid using PayPal. Amount: 300

Explanation

The Strategy Pattern allows for the separation of algorithm-specific logic into separate classes. In the example, different payment methods (Credit Card and PayPal) are encapsulated as strategies. The ShoppingCart context then uses the appropriate strategy to process the payment without being aware of the payment details.

7. When to use?

Use the Strategy Pattern when:

1. Many related classes differ only in their behavior (algorithm).

2. An algorithm has many variations that can be swapped dynamically.

3. The algorithm's logic should be decoupled from its client.


Comments