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() -> voidKonkretny 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 -= dxElement 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
3Historia 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.
Wyzwanie
ŁatwyBohater 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 krokistep_xistep_y.execute()dodaje kroki doxiybohatera, aundo()je odejmuje.CommandHistory:run(command)wykonuje polecenie i je przechowuje.undo_last()cofa najnowsze przechowywane polecenie, usuwa je i zwracatrue; jeśli nic nie jest przechowywane, zwracafalse.
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 undoTwó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())
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe selfMetodyWłaściwościKonstruktor (_init)Powtórka – prosty kalkulator4Polimorfizm
Ponowne omówienie przesłaniania metodDuck typingKlasy i metody abstrakcyjneProjektowanie interfejsówPowtórzenie – kalkulator kształtów7Sygnały
Czym jest sygnał?Deklarowanie i emitowanieŁączenie z sygnałamiSygnały z argumentamiPodsumowanie — system zdrowia10Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu2Właściwości klas
Zmienne instancji a zmienne statyczneFunkcje statyczneSettery właściwościGettery właściwościPrywatne z konwencjiPodsumowanie — menedżer kont bankowych5Enkapsulacja
Elementy publiczne i prywatneWalidacja za pomocą setterówUkrywanie informacjiWłaściwości tylko do odczytuPodsumowanie – system ewidencji uczniów8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieKlasy wewnętrzneWęzły jako komponentyRefCounted a NodeTypy wyliczeniowe w klasach11Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superNadpisywanie metodŁańcuchy dziedziczeniaSprawdzanie typów za pomocą isPodsumowanie – hierarchia pracowników6Metody specjalne
Wprowadzenie do metod wirtualnychMetoda _to_stringWłasne iteratoryPodsumowanie — własna lista9Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator GDScript online