State Design Pattern in Java

In this article, we will do an in-depth exploration of State Design Pattern in Java. So, let’s get started.

What is State Design Pattern in Java ?

State Design Pattern in Java enables the object to change it’s behaviour on change of it’s state.One of the simplest example is Mobile. It behaves differently based on it’s mode – Silent,Vibration and Normal.

UML Diagram

State Design Pattern in Java

Example: State Design Pattern in Java

In the below example, we will implement different behaviours of an aircraft based on it’s states.

Class Diagram: State Design Pattern in Java

Example: State Design Pattern in Java

Java Code

// AircraftState Interface

package com.design.state;

public interface AircraftState {

    public void aircraftStatus();

}

// InFlight Class

package com.design.state;

public class InFlight implements AircraftState {

    @Override
    public void aircraftStatus() {
        System.out.println("Aircraft currently is in mid of flight");
    }

}

// Landing Class

package com.design.state;

public class Landing implements AircraftState {

    @Override
    public void aircraftStatus() {
        System.out.println("Aircraft is now landing");
    }

}

// Parked Class

package com.design.state;

public class Parked implements AircraftState {

    @Override
    public void aircraftStatus() {
        System.out.println("Aircraft is currently parked in the airport");
    }

}

// TakingOff Class

package com.design.state;

public class TakingOff implements AircraftState {

    @Override
    public void aircraftStatus() {
        System.out.println("Aircraft is currently taking off");
    }

}

// Taxiing Class

package com.design.state;

public class Taxiing implements AircraftState {

    @Override
    public void aircraftStatus() {
        System.out.println("Aircraft is currently taxiing on the runway");
    }

}

// AircraftStateContext Class

package com.design.state;

public class AircraftStateContext {

    private AircraftState currentState;

    public AircraftStateContext(AircraftState currentState) {
        this.currentState = currentState;
    }

    public AircraftState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(AircraftState currentState) {
        this.currentState = currentState;
    }

    public void aircraftStatus() {
        currentState.aircraftStatus();
    }

}

// StatePatternDemo Class

package com.design.state;

public class StatePatternDemo {

    public static void main(String[] args) {
        AircraftStateContext aircraftStateContext = new AircraftStateContext(new Parked());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new Taxiing());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new TakingOff());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new InFlight());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new Landing());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new Taxiing());
        aircraftStateContext.aircraftStatus();
        aircraftStateContext.setCurrentState(new Parked());
        aircraftStateContext.aircraftStatus();
    }

}

// Output
Aircraft is currently parked in the airport
Aircraft is currently taxiing on the runway
Aircraft is currently taking off
Aircraft currently is in mid of flight
Aircraft is now landing
Aircraft is currently taxiing on the runway
Aircraft is currently parked in the airport

Use-Cases: State Design Pattern in Java

  1. Contextual Behavior: When an object’s behavior changes based on its internal state, such as the behavior of a vending machine that varies depending on whether it has money or products.
  2. Stateful Objects: When an object undergoes different states and transitions between them, like an order in an e-commerce system progressing from “Pending” to “Shipped” to “Delivered”.
  3. Finite State Machines: When modeling systems with well-defined and distinct states, like traffic lights transitioning from “Red” to “Yellow” to “Green”.
  4. Game Development: In game engines, where game characters have different states such as “Idle,” “Running,” or “Attacking”.
  5. User Interface: When creating interactive user interfaces that change behavior based on user actions or application state.

Pros: State Design Pattern in Java

  1. Modularity: The pattern separates different states into distinct classes, making it easier to manage and modify the behavior of each state independently.
  2. Clean Code: The pattern avoids the use of multiple conditional statements, resulting in cleaner and more maintainable code.
  3. Flexibility: Adding new states or altering existing ones is easier, as it requires creating new state classes without impacting the context or other states.
  4. State Transitions: The transitions between states are explicit and encapsulated, reducing the chances of errors in state transitions.
  5. Readability: The State pattern improves the readability of the code by abstracting the state-specific behavior into separate classes.

Cons: State Design Pattern in Java

  1. Complexity: Introducing multiple state classes can increase complexity, especially for systems with a large number of states.
  2. Overhead: For simple systems, the overhead of creating multiple classes might outweigh the benefits.
  3. Maintenance: Managing and coordinating multiple state classes might require careful maintenance.
  4. Limited Use: The pattern is most effective for systems with distinct states and complex behavior changes.

Best Practices: State Design Pattern in Java

  1. Identify States: Carefully identify the distinct states that your system can have and determine the behaviors associated with each state.
  2. Abstract State Interface: Create an interface or abstract class that defines the methods that each state should implement.
  3. Concrete State Classes: Implement individual state classes that implement the abstract state interface and encapsulate state-specific behavior.
  4. Context Class: Create a context class that maintains a reference to the current state and delegates the behavior to the current state object.
  5. State Transition Management: Implement state transitions carefully, making sure that the context correctly transitions between states.
  6. Encapsulate State Change: Avoid direct state changes in the context class; instead, delegate state changes to the state classes themselves.
  7. Separate Concerns: Keep the state-specific behavior separate from the rest of the application logic.
  8. Testing: Test each state class and the context class individually to ensure that the state transitions and behavior work as expected.
  9. Documentation: Clearly document the purpose and behavior of each state class and their interactions with the context class.
  10. Scalability: Design the state classes to be easily extensible, allowing the addition of new states in the future if needed.

Conclusion: State Design Pattern in Java

State Design Pattern in Java offers a powerful approach to manage an object’s behavior changes based on its internal state. This pattern proves invaluable in scenarios where dynamic behavior alteration is required while maintaining modularity and code readability. By encapsulating each state in separate classes and abstracting their behavior, the State pattern promotes clean and maintainable code.

The practical example of an aircraft’s behavior showcased how different states can influence its actions, providing a clear illustration of the pattern’s application. The extensive list of use-cases demonstrates the pattern’s versatility, from contextual behavior adaptation to game development and UI interactions.

The State pattern’s advantages include clean code, modularity, and flexibility, allowing new states to be introduced without affecting existing ones. However, it’s essential to be mindful of complexity, potential overhead, and careful maintenance, especially in systems with numerous states.

Best practices, such as identifying states, creating abstract state interfaces, and designing context classes, ensure effective implementation. By adhering to these practices and thorough testing, developers can harness the full potential of the State Design Pattern, enhancing the maintainability, scalability, and overall robustness of their Java applications.

Must Read Design Pattern Articles: 

Recommended Books:

Leave a Reply

Your email address will not be published. Required fields are marked *