Menu
CoddyTech

Pola Command

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GDScript di Coddy. Pelajaran 50 dari 65.

Pola Command mengubah sebuah tindakan menjadi object. Object tersebut menyimpan semua yang diperlukan untuk menjalankan tindakan itu, sehingga kamu dapat menyimpannya dalam list, menjalankannya nanti, atau membatalkannya.

Setiap perintah memiliki dua method yang sama, yang dideklarasikan oleh class induk abstrak:

# command.gd
@abstract
class_name Command
extends RefCounted

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

Perintah konkret menyimpan object yang dikenainya, yang disebut receiver, dan data tindakannya. Di sini receiver-nya adalah Hero dengan 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

Invoker menjalankan perintah dan mengingatnya. Invoker tidak perlu tahu apa yang dilakukan suatu perintah:

# 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

Riwayat ini adalah stack: pop_back() mengambil perintah terbaru, jadi pembatalan berjalan mundur melalui tindakan dalam urutan terbalik. Object yang sama memberimu pengikatan ulang tombol (sebuah tombol dipetakan ke perintah), pemutaran ulang (jalankan list yang disimpan lagi), dan antrean giliran.

Referensi berjalan satu arah: perintah menunjuk ke hero, dan hero tidak mengetahui apa pun tentang perintah tersebut. Jika hero juga menyimpan perintahnya, object-object itu akan saling membuat tetap hidup dan tidak akan pernah dibebaskan.

challenge icon

Tantangan

Mudah

Hero bergerak di atas grid, dan setiap gerakan bisa dibatalkan. Command (command.gd) mendeklarasikan execute() dan undo(), sedangkan Hero (hero.gd) memiliki x, y, dan position_text(). Tulis:

  • MoveCommand: konstruktor menyimpan hero serta langkah step_x dan step_y. execute() menambahkan langkah tersebut ke x dan y milik hero, sedangkan undo() menguranginya.
  • CommandHistory: run(command) menjalankan perintah dan menyimpannya. undo_last() membatalkan perintah tersimpan yang paling baru, menghapusnya, lalu mengembalikan true; jika tidak ada yang tersimpan, fungsi ini mengembalikan false.

Kode yang disediakan membaca jumlah tindakan berikutnya, lalu membaca satu tindakan per baris (up, down, left, right, atau undo) dan mencetak posisi setelah setiap tindakan. up mengurangi y sebanyak satu. Untuk urutan right, up, undo, undo, undo, outputnya adalah:

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

Tulis kodemu di move_command.gd dan command_history.gd. main.gd berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

extends Node

func _ready():
	# Kode input/output yang disediakan: biarkan apa adanya
	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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler GDScript online