Menu
CoddyTech

Mẫu phương thức khuôn mẫu

Thuộc phần Lập trình hướng đối tượng trong hành trình GDScript của Coddy. Bài học 53 trên 65.

Mẫu Template Method cố định thứ tự các bước của thuật toán trong lớp cha và cho phép mỗi lớp con hoàn thành một số bước. Phương thức trong lớp cha thực hiện các bước đó chính là phương thức mẫu.

# level.gd
@abstract
class_name Level
extends RefCounted

func play() -> void:
	print("Loading ", get_level_name())
	spawn_enemies()
	print("Level complete!")

@abstract func get_level_name() -> String
@abstract func spawn_enemies() -> void

play() là khuôn mẫu: mỗi màn chơi sẽ tải, tạo kẻ địch và hoàn thành theo thứ tự này. Các bước khác nhau là trừu tượng, nên mỗi lớp con phải viết chúng:

# forest_level.gd
class_name ForestLevel
extends Level

func get_level_name() -> String:
	return "Forest"

func spawn_enemies() -> void:
	print("3 wolves appear")

CaveLevel được viết theo cùng cách, với tên "Cave" và 5 bats appear.

# main.gd
var levels: Array[Level] = [ForestLevel.new(), CaveLevel.new()]
for level in levels:
	level.play()
Loading Forest
3 wolves appear
Level complete!
Loading Cave
5 bats appear
Level complete!

Một bước cũng có thể có giá trị mặc định trong lớp cha mà lớp con có thể ghi đè. Một bước tùy chọn như vậy được gọi là hook:

# level.gd
func play() -> void:
	print("Loading ", get_level_name())
	spawn_enemies()
	if has_boss():
		print("The boss arrives")
	print("Level complete!")

func has_boss() -> bool:
	return false

Chỉ cấp độ ghi đè has_boss() để trả về true mới có dòng trùm. Các lớp con viết các bước, còn lớp cha quyết định khi nào chạy chúng, vì vậy lớp con không sửa play() và mọi cấp độ đều tuân theo cùng một thứ tự.

challenge icon

Thử thách

Trung bình

Trò chơi xuất điểm số theo hai định dạng với cùng các bước. Các hàng là từ điển (dictionary) có "name" và "score".

  • Trong exporter.gd, hãy viết phương thức mẫu (template method) export_rows(rows): hàm này in ra header(), sau đó in ra format_row(row) cho từng hàng, rồi in ra footer(rows). Không in tiêu đề hoặc chân trang nếu chúng là chuỗi rỗng. Các điểm mở rộng header() và footer() mặc định trả về "", còn format_row() là hàm trừu tượng.
  • CsvExporter: tiêu đề là name,score, và một hàng là Ada,12. Không có chân trang.
  • ListExporter: không có tiêu đề, một hàng là * Ada scored 12, và chân trang là Players: N với N là số hàng.

Code được cung cấp đọc định dạng (csv hoặc list), số hàng tiếp theo, rồi đọc mỗi hàng NAME SCORE trên một dòng. Với list, nếu có Ada 12 và Bo 7, đầu ra là:

* Ada scored 12
* Bo scored 7
Players: 2

Hãy viết code trong exporter.gd, csv_exporter.gd và list_exporter.gd. Tệp main.gd chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

extends Node

func _ready():
	# Đoạn code đầu vào/đầu ra đã có sẵn: giữ nguyên
	var style := OS.read_string_from_stdin()
	var rows: Array = []
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		rows.append({"name": parts[0], "score": int(parts[1])})
	var exporter: Exporter = CsvExporter.new()
	if style == "list":
		exporter = ListExporter.new()
	exporter.export_rows(rows)
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch GDScript online