Menu
CoddyTech

Wzorzec polecenia

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 50 z 65.

Wzorzec Command zamienia działanie w obiekt. Obiekt przechowuje wszystko, co jest potrzebne do wykonania działania, więc możesz umieścić go na liście, wykonać później lub cofnąć.

Każde polecenie ma te same dwie metody, zadeklarowane w abstrakcyjnej klasie bazowej:

# command.gd
@abstract
class_name Command
extends RefCounted

@abstract func execute() -> void
@abstract func undo() -> void

Konkretny rozkaz przechowuje obiekt, na którym działa, nazywany odbiorcą, oraz dane akcji. Tutaj odbiorcą jest Hero z var x := 0:

# 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

Element wywołujący uruchamia polecenia i zapamiętuje je. Nie musi wiedzieć, co robi polecenie:

# 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

Historia jest stosem: pop_back() pobiera najnowsze polecenie, więc cofanie przechodzi przez działania w odwrotnej kolejności. Te same obiekty umożliwiają ponowne przypisywanie klawiszy (klawisz jest przypisany do polecenia), odtwarzanie (ponowne uruchomienie zapisanej listy) i kolejki tur.

Referencje działają w jedną stronę: polecenia wskazują na bohatera, a bohater nic o nich nie wie. Gdyby bohater przechowywał również swoje polecenia, obiekty podtrzymywałyby się nawzajem przy życiu i nigdy nie zostałyby zwolnione.

challenge icon

Wyzwanie

Łatwy

Bohater porusza się po siatce, a każdy ruch można cofnąć. Command (command.gd) deklaruje execute() i undo(), a Hero (hero.gd) ma x, y i position_text(). Napisz:

  • MoveCommand: konstruktor przechowuje bohatera oraz kroki step_x i step_y. execute() dodaje kroki do x i y bohatera, a undo() je odejmuje.
  • CommandHistory: run(command) wykonuje polecenie i je przechowuje. undo_last() cofa najnowsze przechowywane polecenie, usuwa je i zwraca true; jeśli nic nie jest przechowywane, zwraca false.

Dostarczony kod odczytuje liczbę kolejnych działań, a następnie jedno działanie w każdym wierszu (up, down, left, right lub undo) i wypisuje pozycję po każdym z nich. up zmniejsza y o jeden. Dla sekwencji right, up, undo, undo, undo wynik to:

right -> (1, 0)
up -> (1, -1)
undo -> (1, 0)
undo -> (0, 0)
Nothing to undo

Twój kod umieść w plikach move_command.gd i command_history.gd. main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

extends Node

func _ready():
	# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
	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())
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator GDScript online