Design Patterns Series 2 - Strategy Pattern
In the Design Patterns Series 1 - Introduction post we introduce the design patterns and why we need it. In this post we will explore the first design pattern in this series.
Strategy Pattern:
this pattern shows you how to extend the concept of OOP from "is-a" into "has-a" concept. we can take mammals as example, All mammals have legs and can walk but some mammals have two legs like human and other has four as horses but each one has its walking technique.
From the programming view we can consider the walk method of mammal object print the sentence "I can walk"
public class Mammal
{
public Mammal() {}
public void Walk()
{
Console.WriteLine("I can walk");
}
}
But these dose not distinguish between human and horse, to do human's walk method should print "I can walk using my two legs" and horses walk method should print "I can walk using my four legs". so we need to two walk methods
public class Mammal
{
public Mammal() {}
public void WalkForHuman()
{
Console.WriteLine("I can walk using my two legs");
}
public void WalkForHorse()
{
Console.WriteLine("I can walk using my four legs");
}
}
if we talk about monkeys which can walk in two legs and two hands ?!! so we will need a method for each type of mammals.
some people will say the solution is inheritance, we can make base class with unimplemented walk method then implement it in the derived class.
public abstract class Mammal
{
public void Walk();
}
public class Human : Mammal
{
public Mammal() {}
public void Walk()
{
Console.WriteLine("I can walk using my two legs");
}
}
public class Horse : Mammal
{
public Mammal() {}
public void Walk()
{
Console.WriteLine("I can walk using my four legs");
}
}
for now it is good solution but we have to implement walk method every time we need a new derived class.we can skip this issue but in the future if we want to modify the walk method we will have to change all walk methods in all derived classes.
Strategy pattern is the solution for these problems we can extend the OOP concepts to wrap the mammal object into human, horse, and monkey objects. we will use inheritance also but with IWalkTechnique interface with MyWalkTechnique method.
public interface IWalkTechnique
{
void MyWalkTechnique();
}
then any mammal(human, horse, monkey) class should implement this interface which means all have to define MyWalkTechnique method.
public class HumanWalkTechique : IWalkTechnique
{
public void MyWalkTechnique()
{
Console.WriteLine("I can walk using my two legs");
}
}
public class HorseWalkTechique : IWalkTechnique
{
public void MyWalkTechnique()
{
Console.WriteLine("I can walk using my four legs");
}
}
now you have got a number of walk techniques you can create objects from to build your code using "has-a" not "is-a" relationship and to store this object we will modify Mammal base class as follows
public abstract class Mammal
{
private IWalkTechnique iWalkTechnique;
public Mammal()
{
}
public void SetWalkTechnique(IWalkTechnique iwalktechnique)
{
iWalkTechnique = iwalktechnique;
}
public void Walk()
{
iWalkTechnique.MyWalkTechnique();
}
}
now when you call walk method of the created object it will call MyWalkTechnique of desired mammal. So the Human, Horse classes will be written as follows:public class Human : Mammal
{
public Human()
{
SetWalkTechnique(new HumanWalkTechique());
}
}
public class Horse : Mammal
{
public Horse()
{
SetWalkTechnique(new HorseWalkTechique());
}
}
lets checking how mammals walkHuman humanObj = new Human();
Horse horseObj = new Horse();
humanObj.Walk();
horseObj.Walk();
these lines of code will print outI can walk using my two legs
I can walk using my four legs
but what about selecting walk technique at runtime, we call SetWalkTechnique method like thatHuman humanObj = new Human();
humanObj.SetWalkTechnique(new HorseWalkTechique());
humanObj.Walk();
this will print out
I can walk using my four legs
the strategy design patterns says you should extract the volatile parts of your code and encapsulate them as objects.you can download the full source code here
Comments
Post a Comment