نمط الحالة
جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 54 من 65.
يمنح نمط State الكائن كائن حالة منفصلًا لكل وضع يمكن أن يكون فيه. يُسند الكائن عمله إلى الحالة الحالية، لذلك يتغير سلوكه عندما تتغير الحالة.
عند وجود بضع حالات، يكون التعداد وmatch كافيين. عندما تتفاعل كل حالة مع عدة إجراءات بطريقتها الخاصة، ينمو match مع كل حالة وكل إجراء. ينقل نمط الحالة قواعد كل حالة إلى صنفها الخاص:
# hero_state.gd
@abstract
class_name HeroState
extends RefCounted
@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroStateتعيد handle() الحالة التالية: كائن حالة جديد للتبديل إليه، أو self للبقاء.
# idle_state.gd
class_name IdleState
extends HeroState
func get_state_name() -> String:
return "Idle"
func handle(action: String) -> HeroState:
if action == "run":
return RunState.new()
return selfتُكتب RunState بالطريقة نفسها: اسمها هو "Running"، و"stop" تُعيد IdleState.new(). يحتفظ البطل، وهو السياق، بالحالة الحالية ويسألها عمّا ينبغي فعله:
# hero.gd
class_name Hero
extends RefCounted
var state: HeroState = IdleState.new()
func handle_action(action: String) -> void:
var next := state.handle(action)
if next != state:
print(state.get_state_name(), " -> ", next.get_state_name())
state = next# main.gd
var hero := Hero.new()
for action in ["stop", "run", "run", "stop"]:
hero.handle_action(action)Idle -> Running
Running -> Idleيعني الإجراء نفسه أشياء مختلفة في حالات مختلفة: لا يفعل "stop" شيئًا أثناء الخمول، ويوقف البطل الجاري تشغيله. توجد كل قاعدة في صنف حالتها، لذا فإن إضافة حالة جديدة، مثل القفز، تعني إضافة صنف جديد.
تُعيد الحالات الحالة التالية بدلًا من تخزين البطل. والحالة التي تحتفظ بالبطل بينما يحتفظ البطل بالحالة ستنشئ دورة مراجع، ولن يُحرَّر أيٌّ من الكائنين أبدًا.
التحدي
سهليكون الباب في حالة Locked أو Closed أو Open. يعرّف DoorState (door_state.gd) الدالتين get_state_name() وhandle(action)، وقد كُتب LockedState (locked_state.gd): تجعل unlock الباب في حالة Closed. اكتب:
ClosedState.handle(): تعيدopenكائنًا جديدًا منOpenState، وتعِيدlockكائنًا جديدًا منLockedState، وفي غير ذلك تعيدself.OpenState.handle(): تعيدcloseكائنًا جديدًا منClosedState، وفي غير ذلك تعيدself.Door.handle_action(action): تطلب من الحالة الحالية الحالة التالية. إذا كان الكائن هو نفسه، فاطبعACTION: still STATE؛ وإلا فاطبعACTION: OLD -> NEWوانتقل إلى الحالة الجديدة.
يبدأ الباب في حالة Locked. يقرأ الكود المزوّد عدد الإجراءات التالية، ثم إجراءً واحدًا في كل سطر، ويطبع الحالة النهائية. بالنسبة إلى open وunlock وopen وlock، يكون الناتج:
open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: Openضع كودك في door.gd وclosed_state.gd وopen_state.gd. يحتوي main.gd على كود الإدخال والإخراج المزوّد، ولا يمكن تعديله.
جرّب بنفسك
extends Node
func _ready():
# كود الإدخال/الإخراج المقدَّم: اتركه كما هو
var door := Door.new()
var count := int(OS.read_string_from_stdin())
for i in count:
door.handle_action(OS.read_string_from_stdin())
print("Final state: ", door.state.get_state_name())
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجّه
1أساسيات البرمجة كائنية التوجه
الملفات الخارجيةمقدمة إلى البرمجة كائنية التوجهالفئات مقابل الكائناتالكلمة المفتاحية selfالأساليبالخصائصالمُنشئ (_init)مراجعة - آلة حاسبة بسيطة4تعدد الأشكال
إعادة النظر في تجاوز الأساليبكتابة الأنواع بأسلوب البطةالفئات والأساليب المجرّدةتصميم الواجهاتمراجعة - حاسبة الأشكال10أنماط التصميم، الجزء الثاني
نمط الأوامرنمط المحوّلنمط المُزيّننمط الطريقة القالبيةنمط الحالةالنمط المركّب2خصائص الأصناف
متغيرات الكائن مقابل المتغيرات الساكنةالدوال الساكنةمُعيِّنات الخصائصمُسترجِعات الخصائصخاص وفقًا للاتفاقيةمراجعة - مدير الحسابات البنكية5التغليف
الأعضاء العامة والخاصةالتحقق من الصحة باستخدام دوال الضبطإخفاء المعلوماتالخصائص للقراءة فقطمراجعة - نظام سجلات الطلاب8مفاهيم متقدمة في البرمجة كائنية التوجه
التركيب مقابل الوراثةالأصناف الداخليةالعُقد كمكوّناتRefCounted مقابل Nodeالتعدادات في الأصنافتدرّب بنفسك: مترجم GDScript عبر الإنترنت