🤔 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);
}

✅ 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());
    }
}

⏸️ 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.");
    }
}

✅ 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);
    }
}

✅ 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
    }
}

🧪 Output

Resuming the music...
Already playing!
Pausing the music...
Already paused.

📦 Structure Summary

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

🧠 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.");
        }
    }
}
  • 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 💥.