Menu
CoddyTech

תבנית העיצוב

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

תבנית Decorator מוסיפה התנהגות לאובייקט על ידי עטיפתו באובייקט אחר עם אותן שיטות. כל עטיפה קוראת לאובייקט שבתוכה ומוסיפה את החלק שלה, ואפשר לערום עטיפות בכל סדר.

# weapon.gd
class_name Weapon
extends RefCounted

func get_damage() -> int:
	return 10

func describe() -> String:
	return "Sword"

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

# fire_enchant.gd
class_name FireEnchant
extends Weapon

var inner: Weapon

func _init(wrapped: Weapon) -> void:
	inner = wrapped

func get_damage() -> int:
	return inner.get_damage() + 5

func describe() -> String:
	return inner.describe() + " + Fire"

‏SharpEnchant‎ נכתב באותו אופן, אבל ‏get_damage()‎ שלו מחזירה את ‏inner.get_damage() * 2‎, והמתודה ‏describe()‎ שלו מוסיפה את ‏" + Sharp".

# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())
Sword: 10
Sword + Fire + Sharp: 30

הקריאות נעות פנימה: SharpEnchant פונה אל FireEnchant, שפונה אל החרב. החרב מחזירה 10, האש הופכת את הערך ל־15, והחדות מכפילה אותו ל־30. בסדר ההפוך, FireEnchant.new(SharpEnchant.new(Weapon.new())), הנזק הוא 10 * 2 + 5, כלומר 25.

בלי דקורטורים, כל שילוב היה דורש תת־מחלקה משלו: FireSword, SharpSword, FireSharpSword וכן הלאה. בעזרתם, שתי מחלקות קטנות מכסות את כל השילובים, והוספת קסם חדש דורשת קובץ אחד נוסף.

challenge icon

אתגר

בינוני

בית קפה מכין משקאות באמצעות מעטרים. Beverage (beverage.gd) מצהירה על cost() ועל description(); הקוד עבור Espresso (espresso.gd, $3) ועבור Tea (tea.gd, $2) כבר נכתב. כל מעטר שומר את המשקה שהוא עוטף ב־inner (הבנאים כבר נכתבו). יש לדרוס את cost() ואת description() ב:

  • Milk: עולה 1 יותר ומוסיף + Milk לתיאור.
  • Mocha: עולה 2 יותר ומוסיף + Mocha.
  • Large: מכפיל את העלות של כל מה שבתוכו ומוסיף Large לפני התיאור.

הקוד שסופק קורא כמה הזמנות מופיעות בהמשך, ואז הזמנה אחת בכל שורה: המשקה (espresso או tea) והתוספות שלו, המיושמות משמאל לימין. עבור espresso milk large ועבור tea mocha milk הפלט הוא:

Large Espresso + Milk: $8
Tea + Mocha + Milk: $5

יש לכתוב את הקוד שלך בקבצים milk.gd, mocha.gd ו־large.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

extends Node

func _ready():
	# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var words := OS.read_string_from_stdin().split(" ")
		var drink: Beverage = Tea.new()
		if words[0] == "espresso":
			drink = Espresso.new()
		for extra in words.slice(1):
			match extra:
				"milk":
					drink = Milk.new(drink)
				"mocha":
					drink = Mocha.new(drink)
				"large":
					drink = Large.new(drink)
		print("%s: $%d" % [drink.description(), drink.cost()])
quiz iconבחנו את עצמכם

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

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

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