Jeff
Jeff

Reputation: 785

switch/case to strategy pattern

I am having a huge switch/case statement which I would like to replace with strategy pattern. Each statement has big peace of code doing the specific logic. Does anyone have a good example of using the pattern in such case, or you have any other good solutions to this?

My solution sofar

class Context
{
    private readonly List<CalculationUnit> _calculationsUnits;

    public Context()
    {
        _calculationsUnits = new List<CalculationUnit>()
                                 {
                                     new CalculationUnitA("calc1"),
                                     new CalculationUnitB("calc2"),
                                     new CalculationUnitC("calc2")
                                 };
    }

    public int Calculate(string name)
    {
        return (from c in _calculationsUnits where c.Name.Equals(name) select c.Calculate()).FirstOrDefault();
    }
}

class CalculationUnit
{
    public string Name { get; private set; }

    public CalculationUnit(string name)
    {
        Name = name;
    }

    public virtual int Calculate()
    {
        return 0;
    }
}

class CalculationUnitA : CalculationUnit
{
    public CalculationUnitA(string name) : base(name) { }

    public override int Calculate()
    {
        //calculations logic A
    }
}

class CalculationUnitB : CalculationUnit
{
    public CalculationUnitB(string name) : base(name) { }

    public override int Calculate()
    {
        //calculations logic A
    }
}

class CalculationUnitC : CalculationUnit
{
    public CalculationUnitC(string name) : base(name) { }

    public override int Calculate()
    {
        //calculations logic A
    }
}

But then I will end up with 50 classes implementing each of the logic...

Thanks

Upvotes: 2

Views: 4687

Answers (1)

David M
David M

Reputation: 72860

The strategy pattern helps here by refactoring out the big piece of code in each branch into a separate class (or method). Your switch then becomes simply a case of selecting the appropriate strategy class (or method delegate), which is then executed at the end of the switch statement by a single call. Thus something roughly like this:

switch (...)
{
    case ...:
        // Horrible logic;
        break;
    ...
}

becomes something like this:

ILogicImplementer implementer;
switch (...)
{
    case ...:
        implementer = new FirstCaseImplementer();
        break;
    ...
}
implementer.Implement();

You need to refactor the logic into a series of classes implementing a common interface (or extending a common base class), or into a series of methods with compatible signatures so that your strategy can be to select a matching delegate. As Oded implies in his comment, you're not necessarily going to get rid of the select doing this, but each case will become a lot smaller.

From your brief description, it does sound like the appropriate approach to make your code simpler and more maintainable.

Upvotes: 8

Related Questions