نمط المُزيّن
جزء من قسم البرمجة كائنية التوجّه في رحلة 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، وما إلى ذلك. باستخدامها، تغطي فئتان صغيرتان كل التركيبات، وتكون إضافة تعويذة جديدة بمثابة إضافة ملف آخر.
التحدي
متوسطيُعِدّ مقهى المشروبات باستخدام المُزيِّنات. يعرّف 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()])
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجّه
1أساسيات البرمجة كائنية التوجه
الملفات الخارجيةمقدمة إلى البرمجة كائنية التوجهالفئات مقابل الكائناتالكلمة المفتاحية selfالأساليبالخصائصالمُنشئ (_init)مراجعة - آلة حاسبة بسيطة4تعدد الأشكال
إعادة النظر في تجاوز الأساليبكتابة الأنواع بأسلوب البطةالفئات والأساليب المجرّدةتصميم الواجهاتمراجعة - حاسبة الأشكال10أنماط التصميم، الجزء الثاني
نمط الأوامرنمط المحوّلنمط المُزيّننمط الطريقة القالبيةنمط الحالةالنمط المركّب2خصائص الأصناف
متغيرات الكائن مقابل المتغيرات الساكنةالدوال الساكنةمُعيِّنات الخصائصمُسترجِعات الخصائصخاص وفقًا للاتفاقيةمراجعة - مدير الحسابات البنكية5التغليف
الأعضاء العامة والخاصةالتحقق من الصحة باستخدام دوال الضبطإخفاء المعلوماتالخصائص للقراءة فقطمراجعة - نظام سجلات الطلاب8مفاهيم متقدمة في البرمجة كائنية التوجه
التركيب مقابل الوراثةالأصناف الداخليةالعُقد كمكوّناتRefCounted مقابل Nodeالتعدادات في الأصنافتدرّب بنفسك: مترجم GDScript عبر الإنترنت