Java design pattern: State

Today we will look at another Java design pattern from the category of behavioral patterns – State. Design patterns in this category deal with the communication (interaction) between objects and their responsibility.

What is the State Design Pattern?

State is a design pattern that allows an object to change its behavior when its internal state changes. In the pattern, we create objects that represent individual states and a context object whose behavior changes depending on the state of the object.

For a better understanding, let’s imagine a simple ticket vending machine. Its behaviour varies depending on what stage of the purchase process (specific state) it is in (e.g. ticket selection, payment, confirmation). Implementing this automated process using the State design pattern would make the code clearer by breaking the business logic of each phase into separate states.

What problem does State’s design pattern solve?

The State pattern solves the problem when an object behaves differently depending on its current state. It allows you to define different states and transitions between them, keeping the state logic separate from the main object logic. This concept is similar to Finite State Machines(FSM ). The behavior of each state is defined independent of the other states, and adding new states should not affect the behavior of existing states.

Example of State implementation in Java

The practical use of the State design pattern will be illustrated with the example of a traffic light with red, orange and green states that controls road traffic.

StavSemaforu.java

package designpatterns;

public interface StavSemaforu {
    void vykonat();
}

The StavSemaforu is the interface that defines the vykonat() method. Each semaphore state (red, orange, green) implements this interface and provides its own implementation of vykonat().

Cervena.java, Oranzova.java, Zelena.java

package designpatterns;

public class Cervena implements StavSemaforu {
    @Override
    public void vykonat() {
        System.out.println("Svetlo na semafore sa preplo na červenú - premávka sa zastavila.");
    }
}

public class Oranzova implements StavSemaforu {
    @Override
    public void vykonat() {
        System.out.println("Svetlo na semafore sa preplo na oranžovú - čaká sa na zmenu.");
    }
}

public class Zelena implements StavSemaforu {
    @Override
    public void vykonat() {
        System.out.println("Svetlo na semafore sa preplo na zelenú - premávka sa rozbieha.");
    }
}

Red, Orange and Green are implementations of the StavSemaforu interface. Each of these classes represents one particular semaphore state and provides its own implementation for vykonat().

Semafor.java

package designpatterns;

// Kontext, ktory prepina stavy
public class Semafor {
    private StavSemaforu stav;

    public Semafor() {
        this.stav = new Oranzova();
    }

    public void prepnut(StavSemaforu novyStav) {
        this.stav = novyStav;
    }

    public void vykonat() {
        stav.vykonat();
    }
}

Semafor is a class that represents a context where semaphore states change. In this case, the Semafor is initialized to the Oranzova state. It has a prepnut() method that changes the current semaphore state to the specified new state. It also has an vykonat() method that executes the current state of the semaphore.

Main.java

import designpatterns.Cervena;
import designpatterns.Oranzova;
import designpatterns.Semafor;
import designpatterns.Zelena;

public class Main {
    public static void main(String[] args) {
        // Semafor je na zaciatku inicializovany na stav oranzova.
        Semafor semafor = new Semafor();
        semafor.vykonat();
        semafor.prepnut(new Cervena());
        semafor.vykonat();
        semafor.prepnut(new Oranzova());
        semafor.vykonat();
        semafor.prepnut(new Zelena());
        semafor.vykonat();
    }
}

In the Main class we simulate the operation of a traffic light. We create an instance of the semaphore that is initially in the orange state. We then change the state of the semaphore using the prepnut() method and then call the vykonat() method, which handles the business logic defined for that state.

The output of this example is:

Example output for Java design patterns: State

Summary

The State pattern is useful to use if we have defined a finite number of states for an object to pass through and we need to perform some action when changing its internal state.

We have prepared the files with the above example in the form of code that you can run directly in Java. Download the Java State code here.

If you’re a Java developer looking for work, check out our employee benefits and respond to our job offers.

About the author

Jozef Wagner

Java Developer Senior

Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

Let us know about you