08 Jan 2025

Strategy Pattern

Overview

The Strategy Pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate them in separate classes, and make them interchangeable. This pattern lets you select an algorithm’s behavior at runtime without modifying the client.

Key Participants

  1. Context

  • Maintains a reference to a Strategy object.

  • Allows the strategy to be dynamically changed.

  • Delegates behavior to the currently selected Strategy.

  1. Strategy

  • Defines the interface for a family of algorithms.

  • Provides an abstract method that concrete strategies must implement.

  1. ConcreteStrategy

  • Implements the Strategy interface with specific behavior.

  • Represents a specific algorithm.

Implementation in Code

Example: Payment System

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

// ConcreteStrategy: Credit Card Payment
class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;

    public CreditCardPayment(String cardNumber) {
        this.cardNumber = cardNumber;
    }

    @Override
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using Credit Card ending in " + cardNumber.substring(cardNumber.length() - 4));
    }
}

// ConcreteStrategy: PayPal Payment
class PayPalPayment implements PaymentStrategy {
    private String email;

    public PayPalPayment(String email) {
        this.email = email;
    }

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

// Context
class ShoppingCart {
    private PaymentStrategy paymentStrategy;

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

    public void checkout(int amount) {
        if (paymentStrategy == null) {
            System.out.println("No payment strategy selected.");
        } else {
            paymentStrategy.pay(amount);
        }
    }
}

// Client
public class StrategyPatternDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        // Pay with Credit Card
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9101-1121"));
        cart.checkout(500);

        // Pay with PayPal
        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(300);
    }
}

Key Methods

  1. setStrategy(Strategy): Allows the context to change the strategy dynamically.

  1. execute(): Defines the behavior of the strategy.

Advantages

  1. Open/Closed Principle: New strategies can be added without modifying existing code.

  1. Encapsulation: Encapsulates algorithms, making them independent of the client.

  1. Interchangeability: Algorithms can be swapped at runtime.

Disadvantages

  1. Increased Complexity: Requires creating a class for each strategy.

  1. Overhead: Using multiple strategies might increase memory and computational overhead.

Real-World Examples

  1. Sorting Algorithms: A sorting application can use different sorting strategies like Bubble Sort, Quick Sort, or Merge Sort.

  1. Payment Systems: Different payment methods such as credit card, PayPal, or bank transfer.

  1. Compression Algorithms: A file compressor can support ZIP, RAR, or GZIP compression.

When to Use the Strategy Pattern?

  • When you need multiple algorithms for a specific task, and the choice can vary at runtime.

  • When you want to isolate algorithm implementation from the client.

  • When adding or changing algorithms should not affect the client code.

← Back to Library