Tutorial

State Design Pattern in Java

Published on August 4, 2022
author

Pankaj

State Design Pattern in Java

State design pattern is one of the behavioral design pattern. State design pattern is used when an Object change its behavior based on its internal state.

State Design Pattern

state design pattern, state design pattern in java, state pattern If we have to change the behavior of an object based on its state, we can have a state variable in the Object. Then use if-else condition block to perform different actions based on the state. State design pattern is used to provide a systematic and loosely coupled way to achieve this through Context and State implementations. State Pattern Context is the class that has a State reference to one of the concrete implementations of the State. Context forwards the request to the state object for processing. Let’s understand this with a simple example. Suppose we want to implement a TV Remote with a simple button to perform action. If the State is ON, it will turn on the TV and if state is OFF, it will turn off the TV. We can implement it using if-else condition like below; TVRemoteBasic.java

package com.journaldev.design.state;

public class TVRemoteBasic {

	private String state="";
	
	public void setState(String state){
		this.state=state;
	}
	
	public void doAction(){
		if(state.equalsIgnoreCase("ON")){
			System.out.println("TV is turned ON");
		}else if(state.equalsIgnoreCase("OFF")){
			System.out.println("TV is turned OFF");
		}
	}

	public static void main(String args[]){
		TVRemoteBasic remote = new TVRemoteBasic();
		
		remote.setState("ON");
		remote.doAction();
		
		remote.setState("OFF");
		remote.doAction();
	}

}

Notice that client code should know the specific values to use for setting the state of remote. Further more if number of states increase then the tight coupling between implementation and the client code will be very hard to maintain and extend. Now we will use State pattern to implement above TV Remote example.

State Design Pattern Interface

First of all we will create State interface that will define the method that should be implemented by different concrete states and context class. State.java

package com.journaldev.design.state;

public interface State {

	public void doAction();
}

State Design Pattern Concrete State Implementations

In our example, we can have two states - one for turning TV on and another to turn it off. So we will create two concrete state implementations for these behaviors. TVStartState.java

package com.journaldev.design.state;

public class TVStartState implements State {

	@Override
	public void doAction() {
		System.out.println("TV is turned ON");
	}

}

TVStopState.java

package com.journaldev.design.state;

public class TVStopState implements State {

	@Override
	public void doAction() {
		System.out.println("TV is turned OFF");
	}

}

Now we are ready to implement our Context object that will change its behavior based on its internal state.

State Design Pattern Context Implementation

TVContext.java

package com.journaldev.design.state;

public class TVContext implements State {

	private State tvState;

	public void setState(State state) {
		this.tvState=state;
	}

	public State getState() {
		return this.tvState;
	}

	@Override
	public void doAction() {
		this.tvState.doAction();
	}

}

Notice that Context also implements State and keep a reference of its current state and forwards the request to the state implementation.

State Design Pattern Test Program

Now let’s write a simple program to test our state pattern implementation of TV Remote. TVRemote.java

package com.journaldev.design.state;

public class TVRemote {

	public static void main(String[] args) {
		TVContext context = new TVContext();
		State tvStartState = new TVStartState();
		State tvStopState = new TVStopState();
		
		context.setState(tvStartState);
		context.doAction();
		
		
		context.setState(tvStopState);
		context.doAction();
		
	}

}

Output of above program is same as the basic implementation of TV Remote without using state pattern.

State Design Pattern Benefits

The benefits of using State pattern to implement polymorphic behavior is clearly visible. The chances of error are less and it’s very easy to add more states for additional behavior. Thus making our code more robust, easily maintainable and flexible. Also State pattern helped in avoiding if-else or switch-case conditional logic in this scenario. State Pattern is very similar to Strategy Pattern, check out Strategy Pattern in Java. Thats all for State design pattern in java, I hope you liked it.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
March 27, 2014

Great explanation, but it’s little bit confusing where it changes the object alternative.

- Neal

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    April 23, 2014

    Hi and thanks for the nice post. The thing that I didn’t understand is what is the purpose of the context its only job is to call doAction() of the provided state, why don’t client code call doAction() of state instead, why do I need to create a Context that its only job is to call doAction() ? Thanks

    - Adelin

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    May 16, 2019

    Hello, Without the context class, there will not be an object that changes its state internally…

    - CeeJay

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      May 15, 2014

      Very good example to understand the state pattern implementation

      - Nisha

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        July 12, 2014

        According to me, this is an anti-pattern. This is like having a method whith a boolean parameter and 2 actions in it, depending on this boolean. It doesn’t respect the seperation of concerns and the single responsability principle : 1 method for 1 action. If i need to do the action 1 in a case and the action 2 in another case i’ll create action 1 and action2 méthods. With the same example : method 1 : public boolean isTheTvOn(); method 2 : public void turnOnTheTv(); method 3 : public void turnOffTheTv(); and determine the action to do in a service layer

        - Mednnet

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        July 16, 2014

        You are correct in the sense that the pattern was not implemented correctly. The context class should use the stored state object to call the doWhatever() method and not go to a series of nested ifs to figure out what to do. In my opinion, it is also better to show this example with three states instead of two. Toggling between two states is too simplistic. So: public abstract class State { public abstract next(Context c); public abstract previous(Context c); } The concrete state classes must define what are the valid transitions from a current state (if any). Applying this to a simple navigation (wizard), you don’t want to allow navigation from the first state to the third and from the third to the first. Only the second state should allow both a previous and next states. The context class should just use the stored (current) state to determine what to do: public class Context { private State current; ... public void setCurrent(State state) { current = state; } public void goNext() { current.next(this); } public void goPrev() { current.prev(this); } } A possible scenario for a concrete state goes as follows: public final class SecondState extends State { private static SecondState INSTANCE = new SecondState(); private SecondState() {} @Override public void next(Context context) { context.setCurrent(ThirdState.getInstance()); System.out.println( "Second to Third state transition" ); } @Override public void previous(Context context) { context.setCurrent(FirstState.getInstance()); System.out.println( "Second to First state transition" ); } } This respects both the separation of concerns and the single responsibility principle.

        - Hector Fontanez

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        April 3, 2018

        Thanks for posting this.

        - Prasanti

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          May 6, 2016

          Unfortunately the explanation is wrong. The client in pattern implementation version also sets the required implementation object, that is not how state pattern works. Blogs like this produce huge content with diluted concepts, which is very bad.

          - Someone Better

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          April 3, 2018

          Yes, I am looking for a standard book that has valid and correct explanations (like SCJP by Kathy Sierra and Bert Bates) of design patterns. If you are aware of any, could you please suggest?

          - JavaAmateur

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            December 25, 2014

            why TVContext needs to implement State interface ? I think its not required.

            - Lalit Upadheyay

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            September 28, 2018

            If TVContext do not implement State interface, we can not call method doAction(), it is method we need to do in this lesson.

            - randauto

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            August 19, 2019

            If the context (here TVContext) starts to implement a state (here State interface), it is more like a decorator pattern than a state machine. It is not necessary that context need to have the same method signature as the state.

            - Ram

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              May 20, 2015

              Please change all the references of “it’s” to “its”. They’re driving me crazy (as I work on my dissertation I am sensitive to these things).

              - DrJ

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                December 20, 2020

                This is just awesome. Explained one of the complex design patterns with such a easy example

                - Praveen Srivastava

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  March 15, 2021

                  here TvContext implements State interface if i do TvContext tv=new TvContext(); tv.setState(tv); tv.doAction(); wont it start looping??

                  - deepak lodhi

                    Try DigitalOcean for free

                    Click below to sign up and get $200 of credit to try our products over 60 days!

                    Sign up

                    Join the Tech Talk
                    Success! Thank you! Please check your email for further details.

                    Please complete your information!

                    Become a contributor for community

                    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                    DigitalOcean Documentation

                    Full documentation for every DigitalOcean product.

                    Resources for startups and SMBs

                    The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                    Get our newsletter

                    Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                    New accounts only. By submitting your email you agree to our Privacy Policy

                    The developer cloud

                    Scale up as you grow — whether you're running one virtual machine or ten thousand.

                    Get started for free

                    Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                    *This promotional offer applies to new accounts only.