תבנית 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 bossEnemyFactory.create_boss("orc", 3) מחזירה Orc עם 300 נקודות חיים.
אתגר
בינוניטבלת יצירה מציינת אויבים ורמות. 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)
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין