Strategy Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases

Strategy Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases

The Strategy pattern in C# is a behavioral design pattern that defines a family of interchangeable algorithms and allows selecting one at runtime.

The Strategy pattern encapsulates different algorithms or behaviors into separate classes that share a common interface. A context object delegates execution to a selected strategy object instead of implementing the algorithm directly. This allows algorithms to be changed dynamically without modifying the context class. The pattern promotes composition over inheritance and helps eliminate large conditional statements. In C#, the Strategy pattern is commonly used in payment processing, sorting systems, validation frameworks, compression utilities, and pricing engines.

Why We Use Strategy Pattern in C#?

We use the Strategy pattern in C# to:

• Switch algorithms dynamically
• Avoid large if-else or switch statements
• Promote composition over inheritance
• Improve maintainability
• Encapsulate algorithms cleanly
• Support Open/Closed Principle
• Simplify testing
• Enable runtime behavior selection

When Should We Use Strategy Pattern in C#?

The Strategy pattern should be used when:

• Multiple algorithms solve the same problem
• Algorithms should be interchangeable
• Runtime algorithm selection is required
• Conditional logic becomes complex
• Similar classes differ only in behavior
• Independent algorithm testing is needed
• Behavior should be configurable dynamically

Common Programming Problems Solved by Strategy Pattern

• Payment processing systems
• Data compression selection
• Sorting algorithms
• Tax calculation engines
• Authentication providers
• Validation systems
• Route planning systems
• Discount calculation systems
• File export formats

Structure of Strategy Pattern in C#

Typical participants:

• Strategy Interface
• Concrete Strategies
• Context
• Client

Basic workflow:

• Client selects strategy
• Context stores strategy reference
• Context delegates execution to strategy
• Strategy performs algorithm

Strategy Pattern Examples in C#

Example 1: Payment Processing System

An application should support multiple payment methods.

using System;

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"Paid {amount} using Credit Card");
    }
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"Paid {amount} using PayPal");
    }
}

public class ShoppingCart
{
    private IPaymentStrategy paymentStrategy;

    public void SetPaymentStrategy(IPaymentStrategy strategy)
    {
        paymentStrategy = strategy;
    }

    public void Checkout(decimal amount)
    {
        paymentStrategy.Pay(amount);
    }
}

public class Program
{
    public static void Main()
    {
        ShoppingCart cart = new ShoppingCart();

        cart.SetPaymentStrategy(new CreditCardPayment());
        cart.Checkout(100);

        cart.SetPaymentStrategy(new PayPalPayment());
        cart.Checkout(200);
    }
}

Example 2: Sorting Strategy System

An application should dynamically switch sorting algorithms.

using System;

public interface ISortStrategy
{
    void Sort(int[] numbers);
}

public class BubbleSort : ISortStrategy
{
    public void Sort(int[] numbers)
    {
        Console.WriteLine("Using Bubble Sort");
    }
}

public class QuickSort : ISortStrategy
{
    public void Sort(int[] numbers)
    {
        Console.WriteLine("Using Quick Sort");
    }
}

public class SortContext
{
    private ISortStrategy strategy;

    public void SetStrategy(ISortStrategy strategy)
    {
        this.strategy = strategy;
    }

    public void ExecuteSort(int[] numbers)
    {
        strategy.Sort(numbers);
    }
}

public class Program
{
    public static void Main()
    {
        SortContext context = new SortContext();

        context.SetStrategy(new BubbleSort());
        context.ExecuteSort(new int[] { 3, 1, 2 });

        context.SetStrategy(new QuickSort());
        context.ExecuteSort(new int[] { 5, 4, 6 });
    }
}

Example 3: File Compression System

Files should be compressed using different compression algorithms.

using System;

public interface ICompressionStrategy
{
    void Compress(string fileName);
}

public class ZipCompression : ICompressionStrategy
{
    public void Compress(string fileName)
    {
        Console.WriteLine($"Compressing {fileName} using ZIP");
    }
}

public class RarCompression : ICompressionStrategy
{
    public void Compress(string fileName)
    {
        Console.WriteLine($"Compressing {fileName} using RAR");
    }
}

public class CompressionContext
{
    private ICompressionStrategy strategy;

    public void SetCompressionStrategy(ICompressionStrategy strategy)
    {
        this.strategy = strategy;
    }

    public void CreateArchive(string fileName)
    {
        strategy.Compress(fileName);
    }
}

public class Program
{
    public static void Main()
    {
        CompressionContext context = new CompressionContext();

        context.SetCompressionStrategy(new ZipCompression());
        context.CreateArchive("project.txt");

        context.SetCompressionStrategy(new RarCompression());
        context.CreateArchive("backup.txt");
    }
}

Most Known Real-World Use Cases in C#

• Payment gateways
• Authentication providers
• Compression libraries
• Validation frameworks
• Sorting and searching systems
• Pricing engines
• Logging providers
• Caching strategies
• Data serialization formats

Advantages of Strategy Pattern in C#

• Eliminates complex conditional logic
• Supports runtime algorithm switching
• Encourages composition over inheritance
• Improves maintainability
• Simplifies testing
• Supports Open/Closed Principle
• Makes algorithms reusable
• Improves code readability

Disadvantages (Weak Points) of Strategy Pattern in C#

• Increases number of classes
• Clients must understand strategy differences
• Simple logic may become over-engineered
• Additional abstraction may add complexity
• Context and strategies may become tightly coupled
• Frequent strategy switching may complicate debugging

Comparison with Similar Patterns

Pattern Main Purpose Behavior Selection Relationship Type Typical Usage Main Difference from Strategy
Strategy Switch algorithms dynamically Runtime selection Composition Payments, sorting Focuses on interchangeable algorithms
State Change behavior by state Automatic transitions Composition Workflow systems Behavior changes according to internal state
Template Method Define algorithm skeleton Inheritance overrides Inheritance Framework workflows Uses inheritance instead of interchangeable objects
Command Encapsulate requests Invoker triggered Composition Undo systems Encapsulates executable operations instead of algorithms
Factory Method Create objects dynamically Creation logic Inheritance Object factories Focuses on object creation instead of behavior selection

Simplified UML-Style Structure

Component Responsibility
Strategy Interface Defines common algorithm contract
ConcreteStrategy Implements specific algorithm
Context Uses selected strategy
Client Selects and configures strategy

Creational Patterns in C#

13. Chain of Responsibility
14. Iterator
15. Momento
16. State
17. Template Method
18. Command
19. Mediator
20. Observer
21. Strategy
22. Visitor