Hi,
i am back with another post.This time it is a new pattern - State Pattern. Consider this scenario : i want to develop a car racing Game. so i have the Car class with ICar interface. i have to increase or decrease the gear in the car so, i have the same methods in the interface. i have an enum for all the gears. as of now, the car has only two gears. so the enum will have two entries - neutral and first gear. the car class implements the IncreaseGear() function
void ICar.IncreaseGear()
{
if (State == GearState.Neutral)
{
State = GearState.FirstGear;
}
}
this is the code for the whole game as of now:
using System;
using System.Collections.Generic;
using System.Text;
namespace StatePattern
{
enum GearState
{
Neutral = 0,
FirstGear =1
}
interface ICar
{
void IncreaseGear();
void DecreaseGear();
}
class Car : ICar
{
GearState State = GearState.Neutral;
public Car()
{
State = GearState.Neutral;
}
#region ICar Members
void ICar.IncreaseGear()
{
if (State == GearState.Neutral)
{
State = GearState.FirstGear;
}
if (State == GearState.FirstGear)
{
//Do nothing
}
}
//this will be implemented later on
void ICar.DecreaseGear()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
}
one - in the enum
two - in the IncreaseGear() function, i will have to put one more if condition
three - in the DecreaseGear() function, i will have to put one more if condition.
thats is ok as i feel that the changes are minimal.
A few days later, i want my car to upgrade and then i introduce a third gear.
again will have to make changes everywhere.
somehow i feel very uncomfortable here. then i think whether there is another way wherein i can make it more flexible and open to enhancement. yes of course, there is a way.
we can treat every individual gear as a state (nothing but another class) and then let the state itself handle what it wants to do.
so we will have a GearState interface. all gears (neutral, first , second etc) implement this interface. The car class composes of the GearState as a member. Car class implements ICar in such a way that it calls the GearState's Increase and Decrease function for the ICar's methods.
Code is as given below :
using System;
using System.Collections.Generic;
using System.Text;
namespace StatePattern
{
interface GearState
{
GearState Increase();
GearState Decrease();
}
public class FirstGear : GearState
{
public FirstGear()
{
}
#region GearState Members
public GearState Increase()
{
Console.WriteLine("first Gear");
return this;
}
public GearState Decrease()
{
Console.WriteLine("reducing the gear state to neutral");
return new Neutral();
}
#endregion
}
public class Neutral : GearState
{
public Neutral()
{
}
#region GearState Members
public GearState Increase()
{
Console.WriteLine("Increasing to First Gear");
return new FirstGear();
}
public GearState Decrease()
{
Console.WriteLine("Cannot decrease Further,already in neutral");
return this;
}
#endregion
}
interface ICar
{
void IncreaseGear();
void DecreaseGear();
}
class Car : ICar
{
GearState State;
public Car()
{
State = new Neutral();
}
#region ICar Members
public void IncreaseGear()
{
State.Increase();
}
public void DecreaseGear()
{
State.Decrease();
}
#endregion
}
}
now if i want to introduce a new gear, i just implement the GearState interface and then implement the functions for increase and decrease. and in the FirstGear class, retru nan instance of SecondGear in the increase Function.
notice how flexible and simple this is.
Happy coding !!!!!
regards,
nandan
No comments:
Post a Comment