In my view, the main difference lies in their intentions. Technically, State and Strategy pattern look very similar.
The main difference lies in:
- The State pattern changes state of the context when it is required and state can be changed many times. So context changes its state or state can set another state
- Strategy pattern sets strategy and strategy can be changed very rarely and context does not change its strategy.
Strategy pattern.
Our abstraction of some Sound strategies:
public interface ISound
{
void Make();
}
And its concrete strategies:
public class DogSoundStrategy : ISound
{
public void Make()
{
Console.WriteLine("Bar");
}
}
public class CatSoundStrategy : ISound
{
public void Make()
{
Console.WriteLine("Meow");
}
}
This is an abstraction of Animal who can make sound:
public abstract class Animal
{
public void MakeSound(ISound sound)
{
sound.Make();
}
}
And concrete animals look like this:
public class Dog : Animal
{
}
public class Cat : Animal
{
}
And then we can call the above code like this:
Dog dog = new Dog();
dog.MakeSound(new DogSoundStrategy()); // there is a small chance
// that you want to change your strategy
Cat cat = new Cat();
cat.MakeSound(new CatSoundStrategy()); // there is a small chance
// that you want to change your strategy
There is a small chance that you want to change your strategy.
State pattern
Imagine you have a computer game where hero can be any super person in the world. Let's call him as Hero. He can run, swim and fly and change its shape to IronMan or SpiderMan. You have a button where you can change its shape or state to IronMan or SpiderMan.
The code of Hero would look like this:
public class Hero
{
IState _state;
public Hero()
{
_state = new SpiderManState();
}
public void Run()
{
_state.Run();
}
public void Swim()
{
_state.Swim();
}
public void Fly()
{
_state.Fly();
}
public void ChangeShape()
{
_state = _state.SetShape();
}
}
Interface of IState would look like this:
public interface IState
{
void Run();
void Swim();
void Fly();
IState SetShape();
}
And concrete states look like this:
public class SpiderManState : IState
{
public void Fly()
{
Console.WriteLine("Spiderman is flying");
}
public void Run()
{
Console.WriteLine("Spiderman is running");
}
public void Swim()
{
Console.WriteLine("Spiderman is swimming");
}
public IState SetShape()
{
return new IronManState();
}
}
and IronManState would look like this:
public class IronManState : IState
{
public void Fly()
{
Console.WriteLine("IronMan is flying");
}
public void Run()
{
Console.WriteLine("IronMan is running");
}
public void Swim()
{
Console.WriteLine("IronMan is swimming");
}
public IState SetShape()
{
return new SpiderManState();
}
}
And now by clicking button ChangeShape() of Hero class, you will be able to change State of hero from,
e.g. SpiderMan to IronMan.
So State of Context (Hero) depends on and can be changed by its button ChangeShape. And it can occur many times.
There is a high chance that you want to change context's state.
State pattern is also can be considered as an alternative to replace many if — else statements in class.