커맨드 패턴
Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 50번째.
Command 패턴은 동작을 객체로 만듭니다. 객체에는 동작을 실행하는 데 필요한 모든 것이 저장되므로, 목록에 보관하거나 나중에 실행하거나 실행을 취소할 수 있습니다.
모든 명령에는 추상 부모 클래스에서 선언된 동일한 두 메서드가 있습니다.
# command.gd
@abstract
class_name Command
extends RefCounted
@abstract func execute() -> void
@abstract func undo() -> void구체 명령은 수신자라고 하는, 해당 명령이 동작하는 객체와 동작의 데이터를 보관합니다. 여기서 수신자는 var x := 0을 가진 Hero입니다:
# move_command.gd
class_name MoveCommand
extends Command
var hero: Hero
var dx: int
func _init(target: Hero, step: int) -> void:
hero = target
dx = step
func execute() -> void:
hero.x += dx
func undo() -> void:
hero.x -= dx호출자는 명령을 실행하고 기억합니다. 명령이 무엇을 하는지는 알 필요가 없습니다:
# command_history.gd
class_name CommandHistory
extends RefCounted
var done: Array[Command] = []
func run(command: Command) -> void:
command.execute()
done.append(command)
func undo_last() -> void:
if done.is_empty():
return
var last: Command = done.pop_back()
last.undo()# main.gd
var hero := Hero.new()
var history := CommandHistory.new()
history.run(MoveCommand.new(hero, 3))
history.run(MoveCommand.new(hero, 2))
print(hero.x)
history.undo_last()
print(hero.x)5
3기록은 스택입니다. pop_back()은 가장 최근 명령을 가져오므로 실행 취소를 하면 작업을 역순으로 되돌아갑니다. 같은 객체를 사용하면 키 재매핑(키를 명령에 연결), 재생(저장된 목록을 다시 실행), 턴 대기열도 구현할 수 있습니다.
참조는 한 방향으로만 이어집니다. 명령이 영웅을 가리키며, 영웅은 명령에 대해 아무것도 모릅니다. 영웅도 명령을 저장한다면 객체들이 서로를 계속 유지해 메모리에서 해제되지 않을 것입니다.
챌린지
쉬움영웅은 격자에서 이동하며, 모든 이동을 되돌릴 수 있습니다. Command(command.gd)는 execute()와 undo()를 선언하고, Hero(hero.gd)에는 x, y와 position_text()가 있습니다. 다음을 작성하세요.
MoveCommand: 생성자는 영웅과 이동량step_x,step_y를 저장합니다.execute()는 이동량을 영웅의x와y에 더하고,undo()는 이동량을 뺍니다.CommandHistory:run(command)는 명령을 실행하고 저장합니다.undo_last()는 가장 최근에 저장한 명령을 실행 취소하고 제거한 다음true를 반환합니다. 저장된 명령이 없으면false를 반환합니다.
제공된 코드는 이어지는 동작의 수를 읽은 다음, 한 줄에 하나씩 동작(up, down, left, right 또는 undo)을 읽고 매 동작 후 위치를 출력합니다. up은 y를 1만큼 낮춥니다. right, up, undo, undo, undo를 입력했을 때 출력은 다음과 같습니다.
right -> (1, 0)
up -> (1, -1)
undo -> (1, 0)
undo -> (0, 0)
Nothing to undo코드는 move_command.gd와 command_history.gd에 작성하세요. main.gd에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.
직접 해보기
extends Node
func _ready():
# 제공된 입출력 코드: 그대로 유지하세요
var hero := Hero.new()
var history := CommandHistory.new()
var steps := {"up": [0, -1], "down": [0, 1], "left": [-1, 0], "right": [1, 0]}
var count := int(OS.read_string_from_stdin())
for i in count:
var action := OS.read_string_from_stdin()
if action == "undo":
if history.undo_last():
print("undo -> ", hero.position_text())
else:
print("Nothing to undo")
else:
var step: Array = steps[action]
history.run(MoveCommand.new(hero, step[0], step[1]))
print(action, " -> ", hero.position_text())
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 GDScript 컴파일러