Menu
CoddyTech
flag Ar iconالعربيةdown icon

نمط المُزيّن

جزء من قسم البرمجة كائنية التوجّه في رحلة 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 عبر الإنترنت