Wednesday, April 18, 2018

Strategy Pattern

I have been reading about design patterns. I realize that I often use them, but could not tell you what the are called or why the are good/bad. I decided to pick up a book, Head First Design Patterns, and look for other resources online as I read. I found a nice Pluralsight video that has many design patters included in the video called Design Patterns Library.

The first pattern in the book is the Strategy Pattern. This allows you to use a family of algorithms and the one that will be used is decided at run time. Each algorithm is encapsulated into the family and makes them interchangeable. This makes it beneficial when you have multiple classes that need an algorithm of the same type, such a speaking behavior, but not all classes implement the behavior in the same way.

Most animals have a form of speaking, dogs bark, cats meow, etc. So, if you take a class of Animal which contains a method for speaking then each class that extends animal will be able to speak. Now you have an issue, you will have to override the speak method for each class that inherits from Animal. That means a lot of extra code, and if the speak behavior ever needs to change you may miss changing one.

This is where the Strategy Pattern can come in handy. Now you have an interface for speaking Animal strategy, say ISpeaking. Then you have classes that extends the interface for different types of animal: dog, cat, etc. These classes will look something like:

public interface IAnimalType
{
   String Speak();
// other things animals need/do
}

public class Dog: IAnimalType
{
public String Speak() 
{
return "I am a dog, here me bark...woof!";
}
}

public class Cat: IAnimalType
{
public String Speak() 
{
  return "I am a cat, here me meow...if you can find me!";
}
}

We can then pull the strategies in an Animal context with code similar to:

public class Animal
{
IAnimalType iAnimalType;
// Other interfaces needed to make a true animal

public Animal(IAnimalType iAnimalType)
{
this.iAnimalType= iAnimalType;
// Your other animal interfaces go here
}

public void Speak()
{
Console.WriteLine(this.iAnimalType.Speak();
}
}

We can go to a employee now and return different request to the HRContext by selecting a strategy.

class Program
{
static void Main(string[] args)
{
Animal dog = new Animal(new DogType());
Animal cat = new Animal(new CatType());

Console.WriteLine("Here is a Dog");
dog.Speak();

Console.WriteLine("Here is a Cat");
cat.Speak();
}
}
If we were to run this program we would get out what each animal says. If we ever need to change what one type of animals speak behavior is, we just change it in one spot and don't need to worry about forgetting one.

Using this pattern also allows us to use an Open/Close principle, which is that the classes are open for extension but closed for modifications. We can add any type of animal and will not need to update our iAnimalType or Animal classes.


"You can't expect to hit the jackpot if you don't put a few nickels in the machine." - Flip Wilson

No comments: