نمط الأمر
جزء من قسم Object Oriented Programming في رحلة Python على Coddy — الدرس 49 من 64.
يقوم نمط الأمر (Command Pattern) بتغليف الطلب ككائن، مما يسمح لك بوضع العمليات في طابور، وتسجيل الطلبات، ودعم وظيفة التراجع. كما أنه يفصل بين الكائن الذي يستدعي العملية والكائن الذي يقوم بتنفيذها.
فيما يلي أصناف الأوامر البسيطة:
class Command:
def execute(self):
pass
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_off()كل أمر يغلف عملية محددة على كائن مستلم.
أنشئ المستقبل (receiver) الذي يقوم بالعمل الفعلي:
class Light:
def turn_on(self):
print("Light is on")
def turn_off(self):
print("Light is off")قم بإنشاء مستدعي (invoker) يقوم بتنفيذ الأوامر:
class RemoteControl:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def press_button(self):
self.command.execute()استخدم نمط الأمر (command pattern):
# إنشاء المستقبل (receiver)
light = Light()
# إنشاء الأوامر
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
# إنشاء المستدعي (invoker)
remote = RemoteControl()
# تنفيذ أوامر مختلفة
remote.set_command(light_on)
remote.press_button()
remote.set_command(light_off)
remote.press_button()إضافة دعم لعمليات التراجع:
class UndoableCommand(Command):
def undo(self):
pass
class LightOnCommand(UndoableCommand):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
def undo(self):
self.light.turn_off()
class SmartRemote:
def __init__(self):
self.last_command = None
def execute_command(self, command):
command.execute()
self.last_command = command
def undo(self):
if self.last_command:
self.last_command.undo()
smart_remote = SmartRemote()
smart_remote.execute_command(LightOnCommand(light))
smart_remote.undo() # يطفئ الضوءالناتج:
Light is on
Light is off
Light is on
Light is offنقطة رئيسية: يحول نمط الأمر (Command Pattern) الطلبات إلى كائنات يمكن تخزينها، وتمريرها، وتنفيذها لاحقاً. لا يحتاج المستدعي (invoker) إلى معرفة كيفية تنفيذ العملية - فهو يكتفي باستدعاء execute() على كائن الأمر. يتيح ذلك ميزات مثل التراجع/الإعادة، وجدولة العمليات، وتسجيل الأوامر.
التحدي
سهلفي هذا التحدي، ستقوم بتنفيذ الفئة الأساسية Command في ملف command.py — وهي اللبنة الأساسية لنمط الأمر (Command Pattern). يركز هذا التمرين بشكل خاص على التغليف (encapsulation): تخزين البيانات بشكل خاص (private) وعرضها بأمان من خلال خاصية (property).
قم فقط بتعديل command.py وفقاً لتعليقات TODO. ستوجهك تعليقات TODO إلى:
- تخزين اسم الأمر كـ سمة خاصة (
_name) - عرضها عبر خاصية للقراءة فقط (
name) - تنفيذ تابع
display_info()الذي يطبع اسم الأمر
ملاحظة: يغطي هذا التحدي فئة Command الأساسية فقط — سيتم تقديم وظائف Invoker و Receiver و undo في دروس لاحقة. إكمال هذه الخطوة يمنحك أساس التغليف الذي يبنى عليه النمط الكامل.
سيتم اختبار تنفيذك بواسطة driver.py، والذي يتحقق من:
- الوظائف الأساسية وتنسيق المخرجات
- الحالات الحدية (المدخلات الفارغة، الرموز الخاصة، الأسماء الطويلة)
- حماية خاصية القراءة فقط (محاولة تنفيذ
obj.name = ...يجب أن تثيرAttributeError) - وجود السمة الخاصة
_name
ورقة مرجعية
يقوم نمط الأمر (Command Pattern) بتغليف الطلب ككائن، مما يسمح لك بوضع العمليات في قائمة انتظار، وتسجيل الطلبات، ودعم وظيفة التراجع.
الهيكل الأساسي للأمر:
class Command:
def execute(self):
pass
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_off()إنشاء مستقبل (receiver) يقوم بالعمل الفعلي:
class Light:
def turn_on(self):
print("Light is on")
def turn_off(self):
print("Light is off")إنشاء مستدعي (invoker) يقوم بتنفيذ الأوامر:
class RemoteControl:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def press_button(self):
self.command.execute()مثال على الاستخدام:
# إنشاء المستقبل
light = Light()
# إنشاء الأوامر
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
# إنشاء المستدعي
remote = RemoteControl()
# تنفيذ أوامر مختلفة
remote.set_command(light_on)
remote.press_button()
remote.set_command(light_off)
remote.press_button()إضافة وظيفة التراجع:
class UndoableCommand(Command):
def undo(self):
pass
class LightOnCommand(UndoableCommand):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
def undo(self):
self.light.turn_off()
class SmartRemote:
def __init__(self):
self.last_command = None
def execute_command(self, command):
command.execute()
self.last_command = command
def undo(self):
if self.last_command:
self.last_command.undo()جرّب بنفسك
# استيراد فئة Command من ملف command.py
from command import Command
# معالج شامل لحالات الاختبار
test_case = input()
if test_case == "basic_test":
obj = Command("Test Name")
obj.display_info()
elif test_case == "validation_test":
obj = Command("Validation Test")
print(f"Name: {obj.name}")
elif test_case == "empty_name_test":
obj = Command("")
obj.display_info()
print(f"Empty name handled: {'Yes' if obj.name == '' else 'No'}")
elif test_case == "property_access_test":
obj = Command("Property Test")
original_name = obj.name
try:
# يجب أن يفشل هذا لأن الاسم خاصية للقراءة فقط
obj.name = "Modified Name"
print("Property protection failed")
except AttributeError:
print("Property protected successfully")
print(f"Name unchanged: {obj.name == original_name}")
elif test_case == "multiple_commands_test":
commands = [
Command("First Command"),
Command("Second Command"),
Command("Third Command")
]
for cmd in commands:
cmd.display_info()
elif test_case == "attribute_test":
obj = Command("Attribute Test")
has_private_name = hasattr(obj, "_name")
print(f"Has _name attribute: {has_private_name}")
elif test_case == "special_chars_test":
obj = Command("!@#$%^&*()_+{}[]|\\:;\"'<>,.?/")
obj.display_info()
elif test_case == "long_name_test":
long_name = "A" * 100
obj = Command(long_name)
obj.display_info()
print(f"Name length: {len(obj.name)}")يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكال