5

I am currently trying to get my head around all of the different Design Patterns, I have been set the task of sorting an IQueryable based on different columns, this is how it is currently implemented:

if (choice == 1)
{ 
    return from Animals in ctx.Animals orderby Animals.AnimalID descending select Animals; 
}
else if (choice == 2)
{ 
    return from Animals in ctx.Animals orderby Animals.Name descending select Animals; 
}
else if (choice == 3)
{ 
    return from Animals in ctx.Animals orderby Animals.Age descending select Animals; 
}

This however seems like a bad code smell to me, it does not have the ability to add different fields or sorting options easily, my tutor has advised me that it would be better to implement the strategy pattern and use a Dictionary to select the strategy implementation we want, However I'm not sure how the Strategy Pattern would be applied to this situation, any helpful tips would be appreciated greatly, if any more information is required, just ask.

dav_i
  • 27,509
  • 17
  • 104
  • 136
JamesZeinzu
  • 235
  • 2
  • 3
  • 12

2 Answers2

9

Applying the strategy pattern, you'd have an ISortStrategy interface, and then several implementations like SortById, SortByName and SortByAge. The interface, and its implementations, would have a method like object Sort(Animal animal); that returns one of the animal's properties.

You'd then just select the proper strategy at runtime, and use it like this:

return from animal in ctx.Animals
       orderby sortStrategy.Sort(animal) descending
       select animal;
dcastro
  • 66,540
  • 21
  • 145
  • 155
  • Thank you for this answer, I think I know where I am going with this now, my only problem is Im not sure how the Dictionary I was told to use comes into play, is it to do with picking which implementation of the interface I use? – JamesZeinzu Nov 28 '13 at 10:45
  • 2
    @user2879468 Yeah you can do something like `Dictionary` to store the different sort strategies in then query it from user input like `ISortStrategy strategy = myDictionary[userInput]` – dav_i Nov 28 '13 at 10:49
  • I guess that the dictionary will be used to index all available strategies.. Does the choice come from user input? I suppose he wants you to have a `IDictionary`, where the key is an identifier (e.g., "name", "age"). The user would enter "name", and you'd use that string to look for the proper strategy in the dictionary. – dcastro Nov 28 '13 at 10:49
  • Thank you, this was exactly what I was looking for! :) I have marked your answer as the correct answer, thanks a million. – JamesZeinzu Nov 28 '13 at 10:53
4

Continuing from @dcastro's answer, regarding dictionaries.

You can create the concrete strategy via a factory class (and get bonus points for using a factory as well):

public static class SortStrategyFactory()
{
    private static Dictionary<string, ISortStrategy> strategyRepository;

    static SortStrategyFactory()
    {
      strategyRepository = new Dictionary<string, ISortStrategy>();
      strategyRepository.Add("ID", new SortById());
      strategyRepository.Add("Name", new SortByName());
      strategyRepository.Add("Age", new SortByAge());
    }

    public static ISortStrategy GetStrategy(string key)
    {
      //todo: add error checking
      return strategyRepository[key];
    }

}

Then your initial code becomes:

ISortStrategy sortStrategy= SortStrategyFactory.GetStrategy(choice);

return from animal in ctx.Animals
       orderby sortStrategy.Sort(animal)
       descending select animal;
Søren
  • 6,517
  • 6
  • 43
  • 47
SWeko
  • 30,434
  • 10
  • 71
  • 106