π§© State Pattern
β Intentβ
- Represent an object's state as dedicated classes, with behavior defined per state
- The current state directly determines which behavior to execute
β Motivationβ
- Separates behavior per state into classes, ensuring clear responsibility separation
- Since each state object knows the transition rules, state control is explicit and manageable
β When to Useβ
- For UI or business flows involving steps, transitions, or mode switching
- When many states are expected and future expansion is likely
β Code Exampleβ
- TypeScript
- PHP
- Python
// ηΆζ
γ€γ³γΏγΌγγ§γΌγΉ
interface DocumentState {
publish(context: DocumentContext): void;
}
// ηΆζ
γ―γ©γΉοΌdraftοΌ
class DraftState implements DocumentState {
publish(context: DocumentContext): void {
console.log("γ¬γγ₯γΌδΎι ΌγιδΏ‘");
context.setState(new ReviewState());
}
}
// ηΆζ
γ―γ©γΉοΌreviewοΌ
class ReviewState implements DocumentState {
publish(context: DocumentContext): void {
console.log("ε
¬ιγγΎγγ");
context.setState(new PublishedState());
}
}
// ηΆζ
γ―γ©γΉοΌpublishedοΌ
class PublishedState implements DocumentState {
publish(context: DocumentContext): void {
console.log("γγ§γ«ε
¬ιζΈγΏγ§γ");
}
}
// γ³γ³γγγΉγ
class DocumentContext {
private state: DocumentState;
constructor() {
this.state = new DraftState();
}
setState(state: DocumentState): void {
this.state = state;
}
publish(): void {
this.state.publish(this);
}
}
// ε©η¨δΎ
const doc = new DocumentContext();
doc.publish(); // β γ¬γγ₯γΌδΎι Ό
doc.publish(); // β ε
¬ι
doc.publish(); // β γγ§γ«ε
¬ιζΈγΏ
<?php
interface DocumentState {
public function publish(DocumentContext $context): void;
}
class DraftState implements DocumentState {
public function publish(DocumentContext $context): void {
echo "γ¬γγ₯γΌδΎι ΌγιδΏ‘\n";
$context->setState(new ReviewState());
}
}
class ReviewState implements DocumentState {
public function publish(DocumentContext $context): void {
echo "ε
¬ιγγΎγγ\n";
$context->setState(new PublishedState());
}
}
class PublishedState implements DocumentState {
public function publish(DocumentContext $context): void {
echo "γγ§γ«ε
¬ιζΈγΏγ§γ\n";
}
}
class DocumentContext {
private DocumentState $state;
public function __construct() {
$this->state = new DraftState();
}
public function setState(DocumentState $state): void {
$this->state = $state;
}
public function publish(): void {
$this->state->publish($this);
}
}
// ε©η¨δΎ
$doc = new DocumentContext();
$doc->publish(); // β γ¬γγ₯γΌδΎι Ό
$doc->publish(); // β ε
¬ι
$doc->publish(); // β γγ§γ«ε
¬ιζΈγΏ
from abc import ABC, abstractmethod
class DocumentState(ABC):
@abstractmethod
def publish(self, context: "DocumentContext"):
pass
class DraftState(DocumentState):
def publish(self, context: "DocumentContext"):
print("γ¬γγ₯γΌδΎι ΌγιδΏ‘")
context.set_state(ReviewState())
class ReviewState(DocumentState):
def publish(self, context: "DocumentContext"):
print("ε
¬ιγγΎγγ")
context.set_state(PublishedState())
class PublishedState(DocumentState):
def publish(self, context: "DocumentContext"):
print("γγ§γ«ε
¬ιζΈγΏγ§γ")
class DocumentContext:
def __init__(self):
self._state: DocumentState = DraftState()
def set_state(self, state: DocumentState):
self._state = state
def publish(self):
self._state.publish(self)
# ε©η¨δΎ
doc = DocumentContext()
doc.publish() # β γ¬γγ₯γΌδΎι Ό
doc.publish() # β ε
¬ι
doc.publish() # β γγ§γ«ε
¬ιζΈγΏ
β Explanationβ
This code applies the State
pattern to switch behavior based on the document's state (Draft
, Review
, Published
).
The State
pattern allows an object to change its behavior based on its internal state, eliminating conditional branches and improving readability and maintainability.
1. Overview of the State Patternβ
-
State: Interface defining behavior for each state
- Represented by
DocumentState
in this code
- Represented by
-
ConcreteState: Implements the
State
interface and provides state-specific behavior- Represented by
DraftState
,ReviewState
, andPublishedState
- Represented by
-
Context: Maintains the current state and delegates behavior to it
- Represented by
DocumentContext
- Represented by
2. Key Classes and Their Rolesβ
-
DocumentState
- Common interface for all states
- Declares the method
publish(context: DocumentContext): void
-
DraftState
- Concrete state for the "draft" phase
- The
publish
method sends a review request and transitions toReviewState
-
ReviewState
- Concrete state for the "under review" phase
- The
publish
method publishes the document and transitions toPublishedState
-
PublishedState
- Concrete state for the "published" phase
- The
publish
method outputs a message indicating that the document is already published
-
DocumentContext
- The context class that maintains the current state
- Calls the state's
publish
method and manages transitions usingsetState
3. UML Class Diagramβ
4. Benefits of the State Patternβ
- Eliminates Conditional Branching: Each state's logic is encapsulated in a separate class
- Extensibility: New states can be added by implementing
DocumentState
- Runtime Flexibility: The state can be changed dynamically during execution
This design clearly separates behavior by state and allows safe, manageable state transitions.
It is especially effective when multiple states exist and each has distinct behavior.