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.

Operation
Behavior depends on 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
Feature
How Thread shows it

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?