Menu
CoddyTech

상태 패턴

Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 54번째.

State 패턴은 객체가 가질 수 있는 각 모드마다 별도의 상태 객체를 제공합니다. 객체는 현재 상태에 작업을 맡기므로, 상태가 바뀌면 동작도 바뀝니다.

상태가 몇 개뿐이라면 enum과 match만으로 충분합니다. 각 상태가 여러 동작에 저마다 다르게 반응하면, 모든 상태와 동작이 추가될 때마다 그 match가 길어집니다. State 패턴은 각 상태의 규칙을 자체 클래스에 넣습니다:

# hero_state.gd
@abstract
class_name HeroState
extends RefCounted

@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroState

handle()는 다음 상태를 반환합니다. 전환할 새 상태 객체 또는 현재 상태를 유지할 self입니다.

# idle_state.gd
class_name IdleState
extends HeroState

func get_state_name() -> String:
	return "Idle"

func handle(action: String) -> HeroState:
	if action == "run":
		return RunState.new()
	return self

RunState도 같은 방식으로 작성됩니다. 이름은 "Running"이고, "stop"은 IdleState.new()를 반환합니다. 주인공인 컨텍스트는 현재 상태를 유지하고, 상태에 무엇을 해야 하는지 묻습니다:

# hero.gd
class_name Hero
extends RefCounted

var state: HeroState = IdleState.new()

func handle_action(action: String) -> void:
	var next := state.handle(action)
	if next != state:
		print(state.get_state_name(), " -> ", next.get_state_name())
		state = next
# main.gd
var hero := Hero.new()
for action in ["stop", "run", "run", "stop"]:
	hero.handle_action(action)
Idle -> Running
Running -> Idle

같은 동작도 상태에 따라 다른 의미를 가집니다. "stop"은 대기 상태에서는 아무것도 하지 않고, 실행 중인 영웅을 멈춥니다. 각 규칙은 해당 상태의 클래스에 있으므로, 점프와 같은 새 상태를 추가하려면 클래스를 하나 새로 만들면 됩니다.

상태는 영웅을 저장하는 대신 다음 상태를 반환합니다. 영웅을 보유한 상태와 그 상태를 보유한 영웅은 참조 순환을 이루게 되며, 두 객체 모두 해제되지 않습니다.

challenge icon

챌린지

쉬움

문은 Locked, Closed 또는 Open 상태입니다. DoorState(door_state.gd)는 get_state_name()과 handle(action)을 선언하며, LockedState(locked_state.gd)는 작성되어 있습니다. unlock은 문을 Closed 상태로 만듭니다. 다음을 작성하세요.

  • ClosedState.handle(): open이면 새 OpenState를 반환하고, lock이면 새 LockedState를 반환하며, 그 외에는 self를 반환합니다.
  • OpenState.handle(): close이면 새 ClosedState를 반환하고, 그 외에는 self를 반환합니다.
  • Door.handle_action(action): 현재 상태에 다음 상태를 요청합니다. 같은 객체라면 ACTION: still STATE를 출력하고, 그렇지 않으면 ACTION: OLD -> NEW를 출력한 뒤 새 상태로 전환합니다.

문은 Locked 상태에서 시작합니다. 제공된 코드는 이어지는 동작의 개수를 읽은 다음, 한 줄에 하나씩 동작을 읽고 최종 상태를 출력합니다. open, unlock, open, lock을 입력하면 출력은 다음과 같습니다.

open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: Open

코드는 door.gd, closed_state.gd, open_state.gd에 작성하세요. main.gd에는 제공된 입출력 코드가 있으며 수정할 수 없습니다.

직접 해보기

extends Node

func _ready():
	# 제공된 입력/출력 코드: 그대로 유지하세요
	var door := Door.new()
	var count := int(OS.read_string_from_stdin())
	for i in count:
		door.handle_action(OS.read_string_from_stdin())
	print("Final state: ", door.state.get_state_name())
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 GDScript 컴파일러