State Pattern
The State Pattern is a behavioral design pattern that lets an object change its behavior when its internal state changes. The object appears as if it changed its class.
On this page
State Pattern in JavaScript
1. Definition
The State Pattern is a behavioral design pattern that lets an object change its behavior when its internal state changes. The object appears as if it changed its class dynamically.
Sources:
2. When Should You Use the State Pattern?
- When an object has multiple states and its behavior changes based on that state.
- When you want to separate the logic for each state out of the main class.
3. How to Implement the State Pattern in JavaScript
Implementation steps (per Refactoring Guru):
-
Identify which class will act as the Context.
This could be an existing class that already contains state-dependent code, or a new one if that logic is spread across multiple classes. -
Declare the State interface.
This interface should contain the methods whose behavior can vary by state (you don't need to list every method of the context if it's not necessary). -
For each real state, create a class implementing the State interface.
Then go through the context's methods and move all the code related to that state into the newly created class. -
When moving code into a State class, if you find it depends on private members of the context:
- You can turn those fields/methods into public ones.
- Or move the logic into a public method on the context and call it from the state (a quick fix, though it may be architecturally messy and can be refactored later).
- Or nest the State class inside the context if the language supports it.
-
In the Context class, add a field referencing the State interface, plus a public setter to change the state.
-
Go back through the context's methods and replace state-checking conditionals with calls to the corresponding method on the state object.
-
To transition the context's state:
Create an instance of the appropriate state class and assign it to the context. This can be done from within the context itself, from within the states themselves, or from the client.
=> Where this happens depends on the specific state class.
Example: Vending Machine (Internet Mode Example)
abstract class Mode {
public abstract type: string;
protected internetContext?: InternetContext;
public abstract connect(): void;
public setInternetContext(internetContext: InternetContext): void {
this.internetContext = internetContext;
}
}
class InternetContext {
private mode!: Mode;
constructor(mode: Mode) {
this.setMode(mode);
}
public setMode(mode: Mode): void {
console.log(`Internet mode set to ${mode.type}.`);
this.mode = mode;
this.mode.setInternetContext(this);
}
public accessInternet(): void {
console.log(`Accessing the internet in ${this.mode.type} mode.`);
this.mode.connect();
}
public turnOff(): void {
console.log("turn off the internet");
this.setMode(new OfflineMode());
}
}
class PrivateMode extends Mode {
public type: "private" = "private";
public connect(): void {
console.log("Connecting to the internet in private mode...");
this.internetContext?.setMode(new PublicMode());
}
}
class PublicMode extends Mode {
public type: "public" = "public";
connect(): void {
console.log("Connecting to the internet in public mode...");
this.internetContext?.setMode(new PrivateMode());
}
}
class OfflineMode extends Mode {
public type: "offline" = "offline";
connect(): void {
console.log("You are offline. Please connect to the internet.");
}
}
const internetPrivate = new InternetContext(new PrivateMode());
internetPrivate.accessInternet();
internetPrivate.turnOff();
internetPrivate.accessInternet();
4. Pros & Cons
Pros:
- Clearly separates the logic for each state.
- Easy to extend, maintain, or add new states.
Cons:
- Increases the number of classes when there are many states.
- Can over-complicate a system where the states are actually simple.
5. Real-World Applications
- Managing the state of a UI component (buttons, forms, modals, etc.).
- Finite State Machines for games, workflows, or business processes.
- Authentication flows, login/logout.
Sources:
