Using a Strategy and Factory Pattern with Dependency Injection

There are a few ways of doing this, but the way I prefer is to inject a list of available strategies into your factory, and then filtering them to return the one(s) you’re interested in.

Working with your example, I’d modify IShippingStrategy to add a new property:

public interface IShippingStrategy
{
    int CalculateShippingCost(Order order);
    string SupportedShippingMethod { get; }
}

Then I’d implement the factory like so:

public class ShippingStrategyFactory : IShippingStrategyFactory
{
    private readonly IEnumerable<IShippingStrategy> availableStrategies;

    public ShippingStrategyFactory(IEnumerable<IShippingStrategy> availableStrategies)
    {
        this.availableStrategies = availableStrategies;
    }

    public IShippingStrategy GetShippingStrategy(Order order)
    {
        var supportedStrategy = availableStrategies
                .FirstOrDefault(x => x.SupportedShippingMethod == order.ShippingMethod);
        if (supportedStrategy == null)
        {
            throw new InvalidOperationException($"No supported strategy found for shipping method '{order.ShippingMethod}'.");
        }

        return supportedStrategy;
    }
}

The main reason I like using it this way is that I never have to come back and modify the factory. If ever I have to implement a new strategy, the factory doesn’t have to be changed. If you’re using auto-registration with your container, you don’t even have to register the new strategy either, so it’s simply a case of allowing you to spend more time writing new code.

Leave a Comment