
State Design Pattern
10/28/2009 1:29 am By Sandarenu Chathurika | Articles: 7
State Pattern is one of the most commonly used design patterns. When we write programs we need it to behave differently based on their state (different property values they have). In our application we have some methods (functionalities), and when we call those methods, there output should vary based on the application’s state.
Let’s say that we have a simple network client application, which can send some data to a server. Possible sates that we can have in here are Connected and Disconnected. We can only send messages to the server if we are already connected to it, if not we cannot send data out. And also if the client is in disconnected state, it should periodically retry to connect to the Server. So how are we going to implement this? Simplest and most common way of doing this is to use if-else statements. Pseudo code for that can look something similar to the code fragment below.
if(connected){
sendData(message);
} else {
retryToConnect();
}
Problems we have in this method is that the logic is hard coded inside the if-else. And also if we want to add new feature like client need to authenticate before sending messages, we’ll have to check many conditions inside if-else statements. Since we have all the business logic inside one big if-else (handling all possible scenarios in one place) it become difficult to read, understand, and test. If we can move logic of handling each scenario in to a different class then it become more clear and easy to develop as well as easy to test, since at onetime we are only worried about one single state.
This is where State Pattern can help up. Here we can identify different states of our application, expected functionalities of those states and state transition logics and encapsulate them together in to different different States.
If we consider the example above we can identify three main states.
· Disconnected
· Connected
· Authenticated

Our application will have a class let’s say “MyNetworkClient”, and it will have a variable to hold the state. MyNetworkClient will be the class where outsiders will access. When we want to do network operation, outside clients will call relevant methods in the MyNetworkClient class and it will pass the call to the state and get the job done. Following is the UML diagram for our application based on State Pattern.

Following is the sample code for our network client developed using state pattern.
public class MyNetworkClient {
private State state;
/**
* Created on: Oct 25, 2009
*
* @Author: sandarenu
*/
public MyNetworkClient() {
state = new Disconnected(this);
}
public void setState(State state) {
System.out.println("Tranfering from [" + this.state + "]State to [" + state + "]State");
this.state = state;
this.state.init();
}
public void sendData(Object message){
this.state.sendData(message);
}
public void init(){
this.state.init();
}
/**
* Created on: Oct 25, 2009
*
* @Author sandarenu
* @param args
*/
public static void main(String[] args) {
MyNetworkClient client = new MyNetworkClient();
client.init();
client.sendData("Test Data");
}
}
public interface State {
void init();
void sendData(Object message);
}
public class Disconnected implements State {
private MyNetworkClient context;
/**
* Created on: Oct 25, 2009
* @Author: sandarenu
* @param context
*/
public Disconnected(MyNetworkClient context) {
this.context = context;
}
@Override
public void init() {
System.out.println("Initializing on Disconnected State.");
if(connect()){
context.setState(new Connected(context));
}
}
@Override
public void sendData(Object message) {
throw new RuntimeException("Cannot send data from ConnectedState");
}
private boolean connect(){
System.out.println("Trying to connect to RemoteHost.");
return true;
}
}
public class Connected implements State {
private MyNetworkClient context;
public Connected(MyNetworkClient context) {
this.context = context;
}
@Override
public void init() {
System.out.println("Initializing on Connected State.");
if(authorize()){
context.setState(new Autharized(context));
}
}
private boolean authorize() {
System.out.println("Performing Authentication with RemoteHost");
return true;
}
@Override
public void sendData(Object message) {
throw new RuntimeException("Cannot send data from ConnectedState");
}
}
public class Autharized implements State {
private MyNetworkClient context;
public Autharized(MyNetworkClient context) {
this.context = context;
}
@Override
public void init() {
System.out.println("Initializing on Autharized State.");
}
@Override
public void sendData(Object message) {
System.out.println("Sending data[" + message + "] out.....");
}
}
When you run above code you’ll get an output like this.
Starting NetworkClient
Initializing on Disconnected State.
Trying to connect to RemoteHost.
Tranfering from [Disconnected@42e816]State to [Connected@9304b1]State
Initializing on Connected State.
Performing Authentication with RemoteHost
Tranfering from [Connected@9304b1]State to [Autharized@190d11]State
Initializing on Autharized State.
Sending data[Test Data] out.....
Feel free to change the code and experiment with it, which is the only way you can improve your knowledge.
Since we did an example first on what is State pattern, now let’s understand it in theory.
Intent - Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. Following is the UML diagram of the State Pattern.

Advantages of State Patten
· Remove if-else style of coding
· Reduces duplication of code by eliminating repeated if/then or switch statements.
· Increased cohesion, here we are putting behavior specific to one state in to one class it's easier to find that specific logic and it's all in one place.
· Easy to extend, if we want to add new state as we wanted to add Authenticated State, we can easily do that by creating new class by extending State interface.
· Easy to test, we can test the behavior specific to easy state separately.
Lets meet next month with another Design Pattern.



Post new comment