상태 패턴
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) -> HeroStatehandle()는 다음 상태를 반환합니다. 전환할 새 상태 객체 또는 현재 상태를 유지할 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 selfRunState도 같은 방식으로 작성됩니다. 이름은 "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"은 대기 상태에서는 아무것도 하지 않고, 실행 중인 영웅을 멈춥니다. 각 규칙은 해당 상태의 클래스에 있으므로, 점프와 같은 새 상태를 추가하려면 클래스를 하나 새로 만들면 됩니다.
상태는 영웅을 저장하는 대신 다음 상태를 반환합니다. 영웅을 보유한 상태와 그 상태를 보유한 영웅은 참조 순환을 이루게 되며, 두 객체 모두 해제되지 않습니다.
챌린지
쉬움문은 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())
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 GDScript 컴파일러