Menu
CoddyTech

תבנית Factory

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 47 מתוך 65.

תבנית Factory מרכזת במקום אחד את הבחירה באיזו מחלקה ליצור. שאר התוכנית מבקשת מהמפעל "גובלין" ומקבלת בחזרה אובייקט, בלי לציין את שם המחלקה Goblin.

למוצרים יש מחלקת אב משותפת, ולכן הקוד שמשתמש בהם עובד עם כל אחד מהם:

# enemy.gd
class_name Enemy
extends RefCounted

var hp := 10

func attack() -> String:
	return "The enemy waits"
# goblin.gd
class_name Goblin
extends Enemy

func attack() -> String:
	return "The goblin stabs"
# orc.gd
class_name Orc
extends Enemy

func attack() -> String:
	return "The orc smashes"

המפעל הוא מחלקה עם static func שהופכת שם לאובייקט. סוג הערך שהיא מחזירה הוא מחלקת האב, ולכן היא יכולה להחזיר כל סוג של אויב, או null עבור שם שאינו מוכר לה:

# enemy_factory.gd
class_name EnemyFactory
extends RefCounted

static func create(kind: String) -> Enemy:
	match kind:
		"goblin":
			return Goblin.new()
		"orc":
			return Orc.new()
	return null
# main.gd
for kind in ["orc", "goblin", "slime"]:
	var enemy := EnemyFactory.create(kind)
	if enemy == null:
		print("Unknown enemy: ", kind)
	else:
		print(enemy.attack())
The orc smashes
The goblin stabs
Unknown enemy: slime

שמות כאלה מגיעים בדרך כלל מנתונים: טבלת הופעה, קובץ שלב או פקודה שהשחקן הקליד. המפעל הוא המקום היחיד שממפה אותם למחלקות, ולכן הוספת Dragon דורשת קובץ חדש אחד וענף חדש אחד בתוך match.

מפעל יכול גם להגדיר את האובייקט לפני שהוא מחזיר אותו, כך שכל מי שקורא לו מקבל אויב שמוכן לשימוש:

static func create_boss(kind: String, level: int) -> Enemy:
	var boss := create(kind)
	if boss != null:
		boss.hp = 100 * level
	return boss

EnemyFactory.create_boss("orc", 3) מחזירה Orc עם 300 נקודות חיים.

challenge icon

אתגר

בינוני

טבלת יצירה מציינת אויבים ורמות. Enemy (enemy.gd) ותת-המחלקה שלו Goblin (goblin.gd) כבר כתובים; השלימו את השאר:

  • ב-orc.gd, הבנאי _init(level) מעביר לבנאי של מחלקת האב את השם Orc, את 25 * level נקודות החיים ואת הנזק 4 + level, כמו שעושה Goblin.
  • ב-enemy_factory.gd, הפונקציה static func create(kind, level) מחזירה Goblin עבור goblin ו-Orc עבור orc, כשהם נוצרים עם אותה רמה. אותיות גדולות בשם אינן משנות (ORC הוא orc). כל שם אחר מחזיר null.

הקוד שסופק קורא כמה אויבים ייווצרו, אחר כך שורת KIND LEVEL אחת לכל אויב, ומדפיס כל אויב או Unknown enemy: KIND, ואז את מספר האויבים שנוצרו. עבור goblin 2, Orc 3 ו-slime 1 הפלט הוא:

Goblin: 20 HP, 4 damage
Orc: 75 HP, 7 damage
Unknown enemy: slime
Spawned: 2

הקוד שלך ייכתב ב-enemy_factory.gd וב-orc.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.

נסו בעצמכם

extends Node

func _ready():
	# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
	var spawned := 0
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		var enemy := EnemyFactory.create(parts[0], int(parts[1]))
		if enemy == null:
			print("Unknown enemy: ", parts[0])
		else:
			spawned += 1
			print(enemy.describe())
	print("Spawned: ", spawned)
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר GDScript אונליין