Strategy Design Pattern in C# with Example

1. Definition

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

2. Problem Statement

Imagine a situation where you have a class with a method that has multiple ways of executing a certain operation. Over time, you might need to add even more ways. This can result in a complex conditional or switch statement, making the method hard to read, maintain, and extend.

3. Solution

The Strategy pattern suggests defining a family of algorithms (strategies), encapsulating each one in a separate class, and making them interchangeable. Instead of implementing a single algorithm directly, the code receives runtime instructions about which strategy to use.

4. Real-World Use Cases

1. E-commerce platforms offering multiple payment methods like credit card, PayPal, and bank transfer.

2. Image compression applications offering different compression algorithms.

3. Route finding applications providing various strategies like quickest, shortest, and scenic routes.

5. Implementation Steps

1. Define a strategy interface common to all supported algorithms.

2. Implement concrete strategy classes for each algorithm.

3. The context class uses the strategy interface to call the algorithm, allowing the strategy to be switched at runtime.

6. Implementation in C#

// Strategy interface
public interface IPaymentStrategy
{
    void Pay(double amount);
}

// Concrete Strategy A
public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(double amount)
    {
        Console.WriteLine($"Paid ${amount} using Credit Card.");
    }
}

// Concrete Strategy B
public class PayPalPayment : IPaymentStrategy
{
    public void Pay(double amount)
    {
        Console.WriteLine($"Paid ${amount} using PayPal.");
    }
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;

    public ShoppingCart(IPaymentStrategy paymentStrategy)
    {
        _paymentStrategy = paymentStrategy;
    }

    public void Checkout(double amount)
    {
        _paymentStrategy.Pay(amount);
    }
}

public class Program
{
    public static void Main()
    {
        ShoppingCart cart1 = new ShoppingCart(new CreditCardPayment());
        cart1.Checkout(100);

        ShoppingCart cart2 = new ShoppingCart(new PayPalPayment());
        cart2.Checkout(200);
    }
}

Output:

Paid $100 using Credit Card.
Paid $200 using PayPal.

Explanation:

In this example, ShoppingCart can use different payment strategies. 

We have defined two strategies: CreditCardPayment and PayPalPayment. At runtime, a shopping cart can switch its payment strategy, allowing flexibility in how payments are processed.

7. When to use?

1. Use the Strategy pattern when there are multiple ways to execute an operation, and these should be selectable at runtime.

2. When you have a lot of similar classes that differ only in how they execute certain behaviors.

3. When you need to decouple classes that invoke operations from classes that perform these operations.


Comments