نمط Strategy
جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 49 من 65.
يضع نمط Strategy كل إصدار من الخوارزمية في كائن مستقل، بحيث يمكنك تبديل الخوارزمية أثناء تشغيل البرنامج. يستدعي الكائن الذي يستخدمها، أي السياق، طريقة واحدة ولا يهتم بالإصدار الذي يحتفظ به.
إليك استراتيجيتا هجوم، وفئة أب وفئة فرعية لهما الطريقة نفسها damage():
# attack_style.gd
class_name AttackStyle
extends RefCounted
func damage(power: int) -> int:
return power# heavy_attack.gd
class_name HeavyAttack
extends AttackStyle
func damage(power: int) -> int:
return power * 2يخزّن السياق استراتيجيةً ويُسند إليها عملية الحساب:
# fighter.gd
class_name Fighter
extends RefCounted
var power := 10
var style: AttackStyle = AttackStyle.new()
func set_style(new_style: AttackStyle) -> void:
style = new_style
func attack() -> void:
print("Hit for ", style.damage(power))# main.gd
var fighter := Fighter.new()
fighter.attack()
fighter.set_style(HeavyAttack.new())
fighter.attack()Hit for 10
Hit for 20لا يتحقق Fighter أبدًا من النمط الذي يستخدمه. كل نمط جديد يعني صنفًا جديدًا، ويظل fighter.gd كما هو؛ أما سلسلة if style == "heavy" داخل attack() فستطول مع كل نمط جديد.
عندما تكون الاستراتيجية دالة صغيرة واحدة لا تملك بيانات خاصة بها، يكون استخدام Callable كافيًا. يخزّن السياق الدالة ويشغّلها باستخدام call():
# price_calculator.gd
class_name PriceCalculator
extends RefCounted
var discount: Callable = func(price): return price
func final_price(price: int) -> int:
return discount.call(price)# main.gd
var calc := PriceCalculator.new()
print(calc.final_price(80))
calc.discount = func(price): return price / 2
print(calc.final_price(80))
calc.discount = func(price): return max(price - 25, 0)
print(calc.final_price(80))80
40
55استخدم الأصناف عندما تكون للاستراتيجية إعداداتها الخاصة أو عدة أساليب، واستخدم العناصر القابلة للاستدعاء لإجراء عملية حسابية قصيرة واحدة. لقد استخدمت هذه الفكرة من قبل: دالة المقارنة التي تمررها إلى sort_custom() هي استراتيجية للفرز.
التحدي
متوسطيمكن لسلة التسوق تبديل استراتيجيات الخصم عند الدفع. Discount في discount.gd هي الاستراتيجية الأساسية: بلا خصم. اكتب استراتيجيتين أخريين والسلة:
PercentOff(تُنشأ باستخدام نسبة مئوية): تُرجعapply(total)القيمةtotal - total * percent / 100(حساب بالأعداد الصحيحة)، وتُرجعlabel()القيمة10% offعند نسبة 10 بالمئة.FixedOff(تُنشأ باستخدام مبلغ): تُرجعapply(total)المجموع مطروحًا منه المبلغ، لكن لا تقل النتيجة أبدًا عن0، وتُرجعlabel()القيمة30 offعند مبلغ 30.Cart: تخزّنset_discount(new_discount)الاستراتيجية، وتجمعcheckout()الأسعار وتُرجعSubtotal TOTAL, LABEL, pay PRICE، حيث إن PRICE هو ما تُرجعهapply()للاستراتيجية.
يقرأ الكود المرفق الأسعار في سطر واحد، وعدد عمليات الدفع التالية، واستراتيجية واحدة في كل سطر: percent N أو fixed N أو none. بالنسبة إلى الأسعار 50 30 40 والاستراتيجيات percent 10 وfixed 30 وnone، يكون الناتج:
Subtotal 120, 10% off, pay 108
Subtotal 120, 30 off, pay 90
Subtotal 120, no discount, pay 120ضع كودك في cart.gd وpercent_off.gd وfixed_off.gd. يحتوي main.gd على كود الإدخال/الإخراج المرفق ولا يمكن تعديله.
جرّب بنفسك
extends Node
func _ready():
# كود الإدخال/الإخراج المقدَّم: اتركه كما هو
var cart := Cart.new()
for price in OS.read_string_from_stdin().split(" "):
cart.add_item(int(price))
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "percent":
cart.set_discount(PercentOff.new(int(parts[1])))
elif parts[0] == "fixed":
cart.set_discount(FixedOff.new(int(parts[1])))
else:
cart.set_discount(Discount.new())
print(cart.checkout())
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجّه
1أساسيات البرمجة كائنية التوجه
الملفات الخارجيةمقدمة إلى البرمجة كائنية التوجهالفئات مقابل الكائناتالكلمة المفتاحية selfالأساليبالخصائصالمُنشئ (_init)مراجعة - آلة حاسبة بسيطة4تعدد الأشكال
إعادة النظر في تجاوز الأساليبكتابة الأنواع بأسلوب البطةالفئات والأساليب المجرّدةتصميم الواجهاتمراجعة - حاسبة الأشكال10أنماط التصميم، الجزء الثاني
نمط الأوامرنمط المحوّلنمط المُزيّننمط الطريقة القالبيةنمط الحالةالنمط المركّب2خصائص الأصناف
متغيرات الكائن مقابل المتغيرات الساكنةالدوال الساكنةمُعيِّنات الخصائصمُسترجِعات الخصائصخاص وفقًا للاتفاقيةمراجعة - مدير الحسابات البنكية5التغليف
الأعضاء العامة والخاصةالتحقق من الصحة باستخدام دوال الضبطإخفاء المعلوماتالخصائص للقراءة فقطمراجعة - نظام سجلات الطلاب8مفاهيم متقدمة في البرمجة كائنية التوجه
التركيب مقابل الوراثةالأصناف الداخليةالعُقد كمكوّناتRefCounted مقابل Nodeالتعدادات في الأصنافتدرّب بنفسك: مترجم GDScript عبر الإنترنت