Strategy Pattern with concrete example

Understanding the Need:

Consider a scenario where the behavior of an algorithm must be dynamically selected at runtime. This is a common challenge in software development, and the knee-jerk reaction might involve a plethora of conditional statements. However, the Strategy Pattern offers an elegant alternative.

Anatomy of Strategy Pattern:

The Strategy Pattern involves defining a family of algorithms, encapsulating each of them, and making them interchangeable. This enables the client to choose a specific algorithm at runtime. Let’s delve into the implementation.

Theoretical Case: Example of Implementation

Begin by creating a context class that includes the strategy:

using System;

public class Context
{
    private IStrategy _strategy;

    public Context(IStrategy strategy)
    {
        this.SetStrategy(strategy);
    }

    public void SetStrategy(IStrategy strategy)
    {
        Console.WriteLine($"Context: Set {strategy.GetType().Name} strategy");
        this._strategy = strategy;
    }

    public void ExecuteStrategy()
    {
        this._strategy.DoSomething();
    }
}

Define an interface for the strategies:

public interface IStrategy
{
    void DoSomething();
}

Implement concrete strategy classes:

public class ConcreteStrategyA : IStrategy
{
    public void DoSomething()
    {
        Console.WriteLine("ConcreteStrategyA is performing the strategy.");
    }
}

public class ConcreteStrategyB : IStrategy
{
    public void DoSomething()
    {
        Console.WriteLine("ConcreteStrategyB is performing the strategy.");
    }
}

// Add more strategies as needed

In the main program, instantiate the context and set and execute different strategies:

public class Program 
{
    public static void Main(string[] args)
    {
        var context = new Context(new ConcreteStrategyA());

        context.ExecuteStrategy();

        context.SetStrategy(new ConcreteStrategyB());
        context.ExecuteStrategy();
    }     
}

Upon execution, you’ll witness the dynamic change of strategies.

Real-world Scenario: E-Commerce Discount Strategies

Let’s apply the Strategy Pattern in a real-world context, such as an e-commerce platform offering various discount strategies.

public interface IDiscountStrategy
{
    double ApplyDiscount(double originalPrice);
}

public class RegularCustomerDiscount : IDiscountStrategy
{
    public double ApplyDiscount(double originalPrice)
    {
        return originalPrice * 0.95; // 5% discount for regular customers
    }
}

public class PrimeMemberDiscount : IDiscountStrategy
{
    public double ApplyDiscount(double originalPrice)
    {
        return originalPrice * 0.85; // 15% discount for prime members
    }
}

In this scenario, the checkout process serves as the context class, dynamically applying different discount strategies based on the customer type:

public class CheckoutProcess(IDiscountStrategy discountStrategy)
{
    public double ProcessOrder(double originalPrice)
    {
        // Additional order processing logic can be added here
        return discountStrategy.ApplyDiscount(originalPrice);
    }
}

Now, in your main program, you can use the CheckoutProcess class to handle orders with different discount strategies.

Conclusion:

The Strategy Pattern emerges as a cornerstone in managing varying algorithms or behaviors within a system. By encapsulating strategies and allowing dynamic switching, this pattern not only fosters flexibility and maintainability but also aligns with SOLID principles.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *