Behavioural - State Pattern
It allows an object to alter its behaviour/context when the state gets changed.

We act differently depending on your mood or situation:
If we’re at office, we are focused and working.
If we're with friends, we're chatting and having fun.
If we're playing sports, we're energetic and competitive.
It’s the same idea: our behavior adapts based on our current state.
The State Pattern helps software do that, switching “rules” automatically when things change.
Think of it like the snack machine at office!
The vending machine can be in two states:
Waiting for a coin (TakeCoinState)
Releasing a product (ReleaseProductState)
The vending machine changes its behavior based on its state:
In coin state: asks for money.
In release state: gives you your chips or drink
The machine is an object that can switch between these states.
Each state has its own simple logic.
When its state changes, its behavior changes—just like the real machine
So, the state pattern let you easy to switch and add new states later!
Low Level Design

Implementation
Interface
public interface VendingMachineState {
void processRequest();
}Context
public class VendingMachineContext {
VendingMachineState state;
public VendingMachineState getState() {
return state;
}
public void setState(VendingMachineState state) {
this.state = state;
}
void doAction() {
state.processRequest();
}
}2 States
public class TakeCoinState implements VendingMachineState {
@Override
public void processRequest() {
System.out.println("Insert coin");
}
}public class ReleaseProductState implements VendingMachineState {
@Override
public void processRequest() {
System.out.println("Releasing product");
}
}Customer
public class Customer {
public static void main(String[] args) {
VendingMachineContext context = new VendingMachineContext();
VendingMachineState state1 = new TakeCoinState();
//Changing the state
context.setState(state1);
//behaviour will be changed
context.doAction();
VendingMachineState state2 = new ReleaseProductState();
//Changing the state
context.setState(state2);
//behaviour will be changed
context.doAction();
}
}Benefits
If you anticipate adding new states in the future, the State pattern facilitates this by allowing you to create new state classes without affecting existing ones.
When conditional statements (if-else or switch-case) become extensive and complex within your object, the State pattern helps organize and separate state-specific behavior into individual classes, enhancing readability and maintainability.
Example in JDK
A Thread has multiple states:
public enum Thread.State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED
}
The same method on Thread behaves differently depending on the current state.
start()
only valid in NEW state; throws IllegalThreadStateException otherwise
run()
only executed in RUNNABLE state
interrupt()
behavior depends on whether thread is WAITING, BLOCKED, or RUNNING
join()
blocks until state becomes TERMINATED
public class ThreadStateExample {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
try { Thread.sleep(200); } catch (Exception ignored) {}
});
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE (or TIMED_WAITING soon)
Thread.sleep(50);
System.out.println(t.getState()); // TIMED_WAITING (while sleeping)
t.join();
System.out.println(t.getState()); // TERMINATED
}
}
Output (varies)
NEW
RUNNABLE
TIMED_WAITING
TERMINATED
Object has internal state
Thread.State enum
Methods behave differently based on state
start(), join(), interrupt(), etc.
State transitions happen during execution
NEW → RUNNABLE → BLOCKED/WAITING → TERMINATED
Client does not manually manage transitions
JVM and scheduler control it
Last updated
Was this helpful?