Skip to main content

State

Overview​

Allow an object to alter its behavior when its internal state changes.

When to use​

  • Behavior varies based on state.
  • You want to avoid large conditionals.
  • State transitions belong inside the object rather than in client code.

Java example​

interface State {
String label();
void publish(Document document);
}

class DraftState implements State {
public String label() {
return "draft";
}

public void publish(Document document) {
document.setState(new PublishedState());
}
}

class PublishedState implements State {
public String label() {
return "published";
}

public void publish(Document document) {
// already published
}
}

class Document {
private State state = new DraftState();

void publish() {
state.publish(this);
}

void setState(State state) {
this.state = state;
}

String render() {
return state.label();
}
}

TypeScript example​

interface State {
label(): string;
publish(document: Document): void;
}

class DraftState implements State {
label(): string {
return 'draft';
}

publish(document: Document): void {
document.setState(new PublishedState());
}
}

class PublishedState implements State {
label(): string {
return 'published';
}

publish(_document: Document): void {}
}

class Document {
private state: State = new DraftState();

publish(): void {
this.state.publish(this);
}

setState(state: State): void {
this.state = state;
}

render(): string {
return this.state.label();
}
}

Pros and cons​

Pros:

  • Removes complex conditional logic.
  • State transitions are explicit.

Cons:

  • More classes for each state.
  • Can be overkill for simple cases.

Common pitfalls​

  • States that leak knowledge of too many other states.
  • Hiding transitions across unrelated services.