نمط الحالة
جزء من قسم البرمجة كائنية التوجه في رحلة Python على Coddy. الدرس 53 من 64.
يسمح نمط الحالة لكائن بتغيير سلوكه عند تغيّر حالته الداخلية. يبدو أن الكائن يغيّر فئته بناءً على حالته الحالية.
إليك فئات حالات بسيطة لإشارة مرور:
class RedState:
def next_state(self, light):
print("Red -> Green")
light.state = GreenState()
def current_color(self):
return "Red"
class GreenState:
def next_state(self, light):
print("Green -> Yellow")
light.state = YellowState()
def current_color(self):
return "Green"
class YellowState:
def next_state(self, light):
print("Yellow -> Red")
light.state = RedState()
def current_color(self):
return "Yellow"تحدّد كل حالة ما يحدث عند الانتقال إلى الحالة التالية.
أنشئ فئة سياق تحتفظ بالحالة الحالية:
class TrafficLight:
def __init__(self):
self.state = RedState() # ابدأ بالأحمر
def change(self):
self.state.next_state(self)
def get_color(self):
return self.state.current_color()يفوّض إشارات المرور السلوك إلى كائن حالته الحالية.
استخدم إشارة المرور:
light = TrafficLight()
print(f"Current: {light.get_color()}")
light.change() # أحمر -> أخضر
print(f"Current: {light.get_color()}")
light.change() # أخضر -> أصفر
print(f"Current: {light.get_color()}")
light.change() # أصفر -> أحمر
print(f"Current: {light.get_color()}")أنشئ مثالًا آخر باستخدام مشغّل بسيط:
class PlayingState:
def play(self, player):
print("Already playing")
def stop(self, player):
print("Stopping music")
player.state = StoppedState()
class StoppedState:
def play(self, player):
print("Starting music")
player.state = PlayingState()
def stop(self, player):
print("Already stopped")
class MusicPlayer:
def __init__(self):
self.state = StoppedState()
def play(self):
self.state.play(self)
def stop(self):
self.state.stop(self)
player = MusicPlayer()
player.play() # بدء تشغيل الموسيقى
player.play() # قيد التشغيل بالفعل
player.stop() # إيقاف الموسيقى
player.stop() # متوقف بالفعلالمخرجات:
Current: Red
Red -> Green
Current: Green
Green -> Yellow
Current: Yellow
Yellow -> Red
Current: Red
Starting music
Already playing
Stopping music
Already stoppedالنقطة الأساسية: يُغلّف نمط الحالة السلوك الخاص بكل حالة في فئات منفصلة، ويتيح لكائن السياق تفويض المهام إلى الحالة الحالية. عند تغيّر الحالة، يتغيّر السلوك تلقائيًا. وهذا يلغي عبارات if/else المعقدة ويجعل إضافة حالات جديدة أسهل.
التحدي
سهلنفّذ نمط الحالة State في state.py لمصباح ذي زر واحد. كل ضغطة تنقل المصباح عبر ثلاث حالات في دورة: متوقف، إضاءة منخفضة، إضاءة عالية، ثم يعود إلى حالة التوقف. بدلًا من سلسلة if تعتمد على سلسلة نصية، تكون كل حالة كائنًا مستقلًا يعرف ما يحدث عند الضغط على الزر.
-
LampStateهو الصنف الأساسي الذي يحتوي علىpress(lamp)وdescribe(). -
OffStateوLowStateوHighStateتنفّذ هذه الدوال: تستدعيpressالدالةlamp.set_state(...)مع الحالة التالية (من التوقف إلى الإضاءة المنخفضة، ومن الإضاءة المنخفضة إلى الإضاءة العالية، ومن الإضاءة العالية إلى التوقف)، وتُرجعdescribeالقيمةLamp is offأوLamp is on lowأوLamp is on high. -
Lampهو السياق: يبدأ في الحالةOffState، وتبدّلset_stateكائن الحالة، وتفوّضpress_buttonالمهمة إلى الحالة الحالية، وتُرجعstatusالوصف الحالي.
الملف driver.py مقفول: فهو يضغط على الزر ويطبع الحالة. لاحظ أن Lamp لا يتحقق أبدًا من الحالة الموجودة فيه؛ فكائنات الحالة هي التي تقرر.
جرّب بنفسك
from state import Lamp
# معالج حالة الاختبار (لا تُغيّر)
test_case = input()
lamp = Lamp()
if test_case == "initial_test":
print(lamp.status())
elif test_case == "one_press_test":
lamp.press_button()
print(lamp.status())
elif test_case == "cycle_test":
for _ in range(4):
print(lamp.status())
lamp.press_button()
elif test_case == "many_presses_test":
for _ in range(7):
lamp.press_button()
print(lamp.status())
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكالتدرّب بنفسك: مترجم Python عبر الإنترنت