
It is a pattern in which actions are performed whenever the object state changes.
On the basis of the new state, a particular action would be taken. We can achieve this by maintaining a state variable and on the basis of that have some if else blocks to perform appropriate tasks.
Let’s look at an example of Car door opening and closing via a remote.
public class CarRemoteExample {
private String carState=null;
public void setState(String carState){
this.carState=carState;
}
public void performAction(){
if(carState.equalsIgnoreCase("OPEN")){
System.out.println("Car door is opened");
}else if(carState.equalsIgnoreCase("CLOSE")){
System.out.println("Car door is closed");
}
}
public static void main(String args[]){
CarRemoteExample cre = new CarRemoteExample();
cre.setState("OPEN");
cre.performAction();
cre.setState("CLOSE");
cre.performAction();
}
}
O/P:
Car door is opened
Car door is closed
As you see above, according to the state which is set the respective action is performed.
But the problem with the above approach is that if the number of states increases would increase the number of if else blocks So the readability and maintainability of the code would be affected.
So to solve this, we can have separate Respective State Classes implementing a State Interface. That State interface would have a single method related to performing action which would be implemented by all sub classes.
public interface State {
public void performAction();
}
public class CarOpenState implements State {
@Override
public void performAction() {
System.out.println("Car door is opened");
}
}
public class CarClosedState implements State {
@Override
public void performAction() {
System.out.println("Car door is Closed");
}
}
Now let’s design a StateContext class which will set the state and trigger the action methods.
public class CarContext implements State {
private State carState;
public void setState(State carState) {
this.carState=carState;
}
public State getState() {
return this.carState;
}
@Override
public void performAction() {
this.carState.performAction();
}
}
Notice that Context also implements State and keep a reference of its current state and forwards the request to the state implementation.
Now let’s test the program.
public class CarDoor {
public static void main(String[] args) {
CarContext context = new CarContext();
State openState = new CarOpenState();
State closeState = new CarCloseState();
context.setState(openState);
context.performAction();
context.setState(closeState);
context.performAction();
}
}
O/P:
Car door is opened
Car door is closed
So according to the states set, the actions are performed.
This pattern is ideal for state based action trigger scenarios.