Table of contents
No headings in the article.
It is one of the behavioral design pattern. This pattern can be used when we have different state of an object. With the help of this pattern we can decide the action of object in a particular state. We can decide the object's behaviour and block the unwanted action of object.
We can achieve same functionality without state pattern. For that we have to use if else in every state action code to check what is the current state and what are the action we can take in this state. It will make code complex and hard to read.
In future if we get more state then we need to change the code every-time. It will be a violation of Open-Closed Principle.
If we take the TV remote example then without using the pattern code will be look like below.
TVRemote.java
public class TVRemote {
private String currentState = "Off";
public void switchOnTV() {
if(currentState.equalsIgnoreCase("off")){
System.out.println("Turning on the TV");
} else if(currentState.equalsIgnoreCase("on")) {
System.out.println("No action needed");
}
}
public void switchOffTV() {
if(currentState.equalsIgnoreCase("On")){
System.out.println("Turning off the TV");
} else if(currentState.equalsIgnoreCase("off")) {
System.out.println("No action needed");
}
}
public void changeChannel() {
if(currentState.equalsIgnoreCase("On")){
System.out.println("changing the channel");
} else if(currentState.equalsIgnoreCase("off")) {
System.out.println("No action needed");
}
}
}
You can see this in the above code. There are already a lot of conditions in small code. It has a tight coupling between implementation and the client code will be very hard to maintain and extend.
Now let's try the state pattern. With the state pattern, the class diagram will look like below.
In the above diagram, state implementation is independent of each other and we can extend easily if we have more states in future.
Here is the code of implementation
State.java
public interface State {
public void action();
}
TurnOnTv.java
public class TurnOnTv implements State {
@Override
public void action() {
System.out.println("Turning on Tv");
}
}
TurnOffTv.java
public class TurnOffTv implements State {
@Override
public void action() {
System.out.println("Turning off Tv");
}
}
ChangeChannel.java
public class ChangeChannel implements State {
@Override
public void action() {
System.out.println("Changing channel");
}
}
TVRemoteContext.java (it will keep the current state)
public class TVRemoteContext implements State {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return this.state;
}
@Override
public void action() {
this.state.action();
}
}
TVRemote.java
public class TVRemote {
public static void main(String[] args) {
TVRemoteContext context = new TVRemoteContext();
State turnOnTv = new TurnOnTv();
State turnOffTv = new TurnOffTv();
State changeChannel = new ChangeChannel();
context.setState(turnOnTv);
context.action();
context.setState(turnOffTv);
context.action();
context.setState(changeChannel);
context.action();
}
}
It looks clean and extendable easily. We can enhance the above code according to requirements. Hope it helps you. Happy reading :)
I explained the strategy pattern in my previous blog checkout anshul007.hashnode.dev/design-pattern-in-ja..