🤔 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
orswitch-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 💥.