상태 패턴은 객체의 상태에 따라 행동을 변경하는 디자인 패턴입니다. 조건문으로 특정 상태를 변경하는 것이 아닌 상태를 객체화하여 필요에 따라 다르게 행동하도록 위임합니다.
State
란 객체가 가질 수 있는 어떤 조건이나 상황을 나타냅니다.
예를 들어 자동차에 시동이 걸려있는 상태라면 속력을 올리거나 줄일 수 있습니다. 만약 자동차의 시동이 꺼지는 상태라면 속력을 올리거나 줄일 수 없습니다. 자동차 시동 상태에 따라 메소드가 달라집니다.
State 패턴을 이용하여 신호등을 구현하는 간단한 예시코드입니다.
TrafficLightContext.ts
현재 상태(TrafficLightState
)를 유지하고, 상태 전환 요청(changeLight
)을 처리합니다.
import { TrafficLightState } from "./TrafficLightState";
// Context 클래스: 현재 신호등 상태를 관리하는 클래스
export class TrafficLightContext {
private state: TrafficLightState;
constructor(state: TrafficLightState) {
this.state = state;
}
public setState(state: TrafficLightState): void {
this.state = state;
}
public renderCurrentTraffic() {
this.state.renderTraffic();
}
public changeState(): void {
this.state.changeLight(this);
}
}
TrafficLightState.ts
상태의 인터페이스로, 모든 구체적인 상태 클래스는 이 인터페이스를 구현합니다.
import { TrafficLightContext } from "./TrafficLightContext";
// State 인터페이스
export interface TrafficLightState {
changeLight(context: TrafficLightContext): void;
renderTraffic(): void;
}
RedLight.ts
changeLight
메서드를 통해 상태를 변경합니다.
renderTraffic
메서드를 통해 UI를 렌더링합니다.
빨간불 ⇒ 초록불로 상태를 변경합니다.
import { GreenLight } from "./GreenLight";
import { TrafficLightContext } from "./TrafficLightContext";
import { TrafficLightState } from "./TrafficLightState";
// ConcreteState 클래스 - 빨간불
export class RedLight implements TrafficLightState {
private static instance: RedLight;
public static getInstance(): RedLight {
if (!RedLight.instance) {
RedLight.instance = new RedLight();
}
return RedLight.instance;
}
public renderTraffic() {
const redTraffic = document.querySelector(".red")!;
const yellowTraffic = document.querySelector(".yellow")!;
const greenTraffic = document.querySelector(".green")!;
const message = document.querySelector(".message")!;
yellowTraffic.classList.remove("active");
greenTraffic.classList.remove("active");
redTraffic.classList.add("active");
message.textContent = "빨간불: 차량 정지!";
}
public changeLight(context: TrafficLightContext): void {
context.setState(GreenLight.getInstance());
}
}
YellowLight.ts
changeLight
메서드를 통해 상태를 변경합니다.
renderTraffic
메서드를 통해 UI를 렌더링합니다.
노란불 ⇒ 빨간불로 상태를 변경합니다.
import { RedLight } from './RedLight';
import { TrafficLightContext } from "./TrafficLightContext";
import { TrafficLightState } from "./TrafficLightState";
// ConcreteState 클래스 - 노란불
export class YellowLight implements TrafficLightState {
private static instance: YellowLight;
static getInstance(): YellowLight {
if (!YellowLight.instance) {
YellowLight.instance = new YellowLight();
}
return YellowLight.instance;
}
public renderTraffic() {
const redTraffic = document.querySelector(".red")!;
const yellowTraffic = document.querySelector(".yellow")!;
const greenTraffic = document.querySelector(".green")!;
const message = document.querySelector(".message")!;
redTraffic.classList.remove("active");
greenTraffic.classList.remove("active");
yellowTraffic.classList.add("active");
message.textContent = "노란불: 신호 변경 주의!";
}
public changeLight(context: TrafficLightContext): void {
context.setState(RedLight.getInstance());
}
}
GreenLight.ts
changeLight
메서드를 통해 상태를 변경합니다.
renderTraffic
메서드를 통해 UI를 렌더링합니다.
초록불 ⇒ 노란불로 상태를 변경합니다.
import { TrafficLightContext } from "./TrafficLightContext";
import { TrafficLightState } from "./TrafficLightState";
import { YellowLight } from "./YellowLight";
// ConcreteState 클래스 - 초록불
export class GreenLight implements TrafficLightState {
private static instance: GreenLight;
public static getInstance(): GreenLight {
if (!GreenLight.instance) {
GreenLight.instance = new GreenLight();
}
return GreenLight.instance;
}
public renderTraffic() {
const redTraffic = document.querySelector(".red")!;
const yellowTraffic = document.querySelector(".yellow")!;
const greenTraffic = document.querySelector(".green")!;
const message = document.querySelector(".message")!;
yellowTraffic.classList.remove("active");
redTraffic.classList.remove("active");
greenTraffic.classList.add("active");
message.textContent = "초록불: 차량 출발";
}
public changeLight(context: TrafficLightContext): void {
context.setState(YellowLight.getInstance());
}
}
changeState
메서드를 호출하여 상태를 변경하며, renderCurrentTraffic
메서드를 호출하여 상태에 따른 UI를 업데이트합니다.changeLight
, renderTraffic
메서드를 정의하고, 구체적인 상태 클래스들(RedLight
, YellowLight
, GreenLight
)이 이 메서드를 구현합니다.Context
는 새로운 상태를 설정하고, 해당 상태의 renderTraffic
메서드를 호출하여 UI를 업데이트합니다.State 패턴은 객체의 상태에 따라 동작을 달리하는 디자인 패턴으로, 조건문 대신 상태를 객체로 캡슐화하여 관리합니다. 이를 통해 코드의 가독성과 유지보수성이 향상됩니다. 각 상태는 자신의 동작을 관리하며, 상태 전이는 명확하게 정의됩니다. 그러나 상태가 많아지면 클래스가 증가할 수 있어 복잡성이 커질 수 있습니다.