DEV Community

Dev Cookies
Dev Cookies

Posted on

๐Ÿ“ Day Nine: State Design Pattern in Java

๐Ÿค” What is the State Pattern?

The State Pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

โ€œInstead of using if-else or switch-case to manage state transitions, encapsulate behaviors in separate state classes.โ€


๐Ÿง  Real-Life Analogy

Imagine a Vending Machine:

  • Idle State: Waiting for selection
  • Processing State: Taking money
  • Dispensing State: Giving the item
  • OutOfStock State

Each state has its own behavior and transitions.


โœ… When to Use

  • When an objectโ€™s behavior depends on its state.
  • When multiple conditional branches exist based on state.
  • When the state transitions are frequent and complex.

๐Ÿ— Example Use Case: Media Player

Letโ€™s build a Media Player that can be in either:

  • PlayingState
  • PausedState

๐Ÿ› ๏ธ Java Implementation of State Pattern


โœ… 1. Define the State Interface

public interface State {
    void play(MediaPlayerContext context);
    void pause(MediaPlayerContext context);
}
Enter fullscreen mode Exit fullscreen mode

โœ… 2. Create Concrete States

๐ŸŽต Playing State

public class PlayingState implements State {
    @Override
    public void play(MediaPlayerContext context) {
        System.out.println("Already playing!");
    }

    @Override
    public void pause(MediaPlayerContext context) {
        System.out.println("Pausing the music...");
        context.setState(new PausedState());
    }
}
Enter fullscreen mode Exit fullscreen mode

โธ๏ธ Paused State

public class PausedState implements State {
    @Override
    public void play(MediaPlayerContext context) {
        System.out.println("Resuming the music...");
        context.setState(new PlayingState());
    }

    @Override
    public void pause(MediaPlayerContext context) {
        System.out.println("Already paused.");
    }
}
Enter fullscreen mode Exit fullscreen mode

โœ… 3. Context Class

public class MediaPlayerContext {
    private State state;

    public MediaPlayerContext() {
        // Default state
        this.state = new PausedState();
    }

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

    public void pressPlay() {
        state.play(this);
    }

    public void pressPause() {
        state.pause(this);
    }
}
Enter fullscreen mode Exit fullscreen mode

โœ… 4. Client Code

public class StatePatternDemo {
    public static void main(String[] args) {
        MediaPlayerContext player = new MediaPlayerContext();

        player.pressPlay();   // Resuming
        player.pressPlay();   // Already playing
        player.pressPause();  // Pausing
        player.pressPause();  // Already paused
    }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช Output

Resuming the music...
Already playing!
Pausing the music...
Already paused.
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“ฆ Structure Summary

+-------------------+          +------------------+
|     Context       |<>------->|      State       |
+-------------------+          +------------------+
| - state: State    |          | + play(context)  |
| + pressPlay()     |          | + pause(context) |
| + pressPause()    |          +------------------+
+-------------------+
        ^                              ^
        |                              |
+------------------+         +------------------+
|  PlayingState    |         |  PausedState     |
+------------------+         +------------------+
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  Benefits

Benefit Explanation
Cleaner Code Avoids if-else hell based on state
Encapsulation Each state encapsulates its logic
Flexibility Easy to add/remove new states
Open/Closed Principle Add states without modifying existing code

๐Ÿ› ๏ธ Real Use Cases

  • Thread lifecycle management
  • UI elements (enabled, disabled, hovered, clicked)
  • TCP Connection (LISTENING, SYN_SENT, ESTABLISHED)
  • Traffic light system ๐Ÿšฆ

๐Ÿšซ Without State Pattern (Messy Approach)

public class MediaPlayerBad {
    private String state = "PAUSED";

    public void pressPlay() {
        if (state.equals("PAUSED")) {
            System.out.println("Resuming music...");
            state = "PLAYING";
        } else {
            System.out.println("Already playing.");
        }
    }

    public void pressPause() {
        if (state.equals("PLAYING")) {
            System.out.println("Pausing music...");
            state = "PAUSED";
        } else {
            System.out.println("Already paused.");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Hard to manage as more states are added
  • Violates Open/Closed Principle

๐Ÿง  Bonus Tips

  • Can be combined with Strategy if states have interchangeable behaviors.
  • Helps a lot in game development and simulations.

โœ… Summary Table

Element Role
State Interface for all states
PlayingState, PausedState Concrete states
MediaPlayerContext Maintains the current state
Client Triggers actions

๐Ÿš€ Thatโ€™s a wrap for Day 9!

Tomorrow for Day 10, weโ€™ll finish strong with the powerful Strategy Pattern โ€” used all over the place in Java APIs like Comparator, payment systems, and sorting algorithms.

Wanna continue? Just say "Day 10" and weโ€™ll wrap up the series with a bang ๐Ÿ’ฅ.

Top comments (0)