Professional Documents
Culture Documents
articles
Q&A
forums
mnacho2
lounge
CPOL
Rate:
Is your email address OK? You are signed up for our newsletters but your email address is either
unconfirmed, or has not been reconfirmed in a long time. Please click here to have a confirmation
email sent so we can confirm your email address and start sending you newsletters again.
Alternatively, you can update your subscriptions.
Introduction
This article describes what is state pattern, when could we find state pattern useful and how to have a rudimentary
implementation of state pattern in C#.
Background
There are times when we find some scenarios in our application when we need to maintain the state of a sub system.
This state needs to be changed based on some conditions and/or user actions. One way to keep track of such states is
by using the conditional logic in code.
Using conditional logic will get us the desired result but that would result in a code that is less understandable and is
harder to maintain. Also, if we need to add more states in the system then that is very difficult and could create
problems in existing system too.
To tackle such problems efficiently, GoF suggest use of State pattern. GoF defines state pattern as "Allow an object to
alter its behavior when its internal state changes. The object will appear to change its class."
It can also be thought of as an object oriented state machine. Let us see the major classes in this pattern.
Context: This is the actual object who is accessed by the client. The state of this object needs to be tracked.
State: This is an interface or abstract class that defines the common behavior associated with all the possible
states of the Context.
ConcreteState: This class represent a state of the Context. Each state will be represented as one concrete
class.
class NoStateATM
{
public enum MACHINE_STATE
{
NO_CARD,
CARD_VALIDATED,
CASH_WITHDRAWN,
}
private MACHINE_STATE currentState = MACHINE_STATE.NO_CARD;
private int dummyCashPresent = 1000;
public string GetNextScreen()
{
switch (currentState)
{
case MACHINE_STATE.NO_CARD:
// Here we will get the pin validated
return GetPinValidated();
break;
case MACHINE_STATE.CARD_VALIDATED:
// Lets try to withdraw the money
Copy Code
return WithdrawMoney();
break;
case MACHINE_STATE.CASH_WITHDRAWN:
// Lets let the user go now
return SayGoodBye();
break;
}
return string.Empty;
}
private string GetPinValidated()
{
Console.WriteLine("Please Enter your Pin");
string userInput = Console.ReadLine();
// lets check with the dummy pin
if (userInput.Trim() == "1234")
{
currentState = MACHINE_STATE.CARD_VALIDATED;
return "Enter the Amount to Withdraw";
}
// Show only message and no change in state
return "Invalid PIN";
}
private string WithdrawMoney()
{
string userInput = Console.ReadLine();
int requestAmount;
bool result = Int32.TryParse(userInput, out requestAmount);
if (result == true)
{
if (dummyCashPresent < requestAmount)
{
// Show only message and no change in state
return "Amount not present";
}
dummyCashPresent -= requestAmount;
currentState = MACHINE_STATE.CASH_WITHDRAWN;
return string.Format(@"Amount of {0} has been withdrawn. Press Enter to proceed", requestAmount);
}
// Show only message and no change in state
return "Invalid Amount";
}
private string SayGoodBye()
{
currentState = MACHINE_STATE.NO_CARD;
return string.Format("Thanks you for using us, Amount left in ATM: {0}", dummyCashPresent.ToString());
}
}
Now when we run the class we can see that this works perfectly from the functionality perspective.
The problem will come when we need to add more states. Whenever we need to add more states to this ATM
machine we need to open up the ATM machine code and then add more logic inside this class itself which is a clear
violoation of Open-Close priciple. Also since we have all that state managed in form of conditional logic, there are
some possibilities that changing code to add new states will break existing functionality too i.e. this way is more error
prone.
So, what would be the better way to do this? The better way to do this is by implementing the same solution using
state pattern. The only thing that we need to do is "encapsulate what varies". So we will go ahead and pull the state
related logic from the ATM class and create seprate classes for each state.
Let us start by modifying the ATM class so that it will contain no state related information. It will only keep an handle
to the object which keeps track of its state.
Hide Copy Code
Copy Code
Copy Code
Copy Code
Console.ReadLine();
return string.Empty;
}
private void UpdateState()
{
// nothing here as someone will have to fill in cash and then
// restart the atm, once restarted it will be in no card state
}
}
And a minor modification in the UpdateState function of the CardValidatedState class.
Hide Copy Code
Before wrapping up let us look at the clas diagram of our application and compare it with the class diagram of GoF.
Point of interest
In this article we tried to get an overviwe of the state pattern and when could it be used. We also implemented as
small application that contains a rudimentaty implementation of state pattern.
History
05 November 2012: First version.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Share
EMAIL
Understanding and
Implementing Decorator
Pattern in C#
Understanding JavaScript
Object Creation Patterns
Search Comments
Go
First Prev Next
25-Jul-14 22:07
19-Dec-13 18:40
My vote of 5
Member 10033741
7-May-13 9:23
News
1
Suggestion
Question
Bug
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.151018.1 | Last Updated 12 Nov 2012
Select Language
Layout: fixed |
fluid