تخطَّ إلى المحتوى

🧩 شرح أنماط التصميم (Design Patterns)

نمط Command

الدرس 8 من 24· ⏱ 2 دقائق قراءة

ما هو نمط Command؟

نمط Command يحوّل الطلب (Request) إلى كائن مستقل—يحتوي على كل معلومات الطلب. هذا يسمح بتمرير الطلبات كمعاملات، تأجيل تنفيذها، و دعم Undo/Redo.

المشكلة

تطبيق محرر نصوص—كل عملية (كتابة، حذف، قص، لصق) تحتاج أن تدعم التراجع والإعادة. بدون نمط Command، كود الـ Undo يصبح فوضويًا.

الحل

// Command interface
class Command {
  execute() {}
  undo() {}
}

// Receiver — المستلم الفعلي للأوامر
class TextEditor {
  constructor() {
    this.content = '';
  }

  write(text) {
    this.content += text;
  }

  delete(count) {
    const deleted = this.content.slice(-count);
    this.content = this.content.slice(0, -count);
    return deleted;
  }

  show() {
    console.log(`📄 ${this.content}`);
  }
}

// Concrete Commands
class WriteCommand extends Command {
  constructor(editor, text) {
    super();
    this.editor = editor;
    this.text = text;
  }

  execute() {
    this.editor.write(this.text);
  }

  undo() {
    this.editor.delete(this.text.length);
  }
}

class DeleteCommand extends Command {
  constructor(editor, count) {
    super();
    this.editor = editor;
    this.count = count;
    this.deletedText = '';
  }

  execute() {
    this.deletedText = this.editor.delete(this.count);
  }

  undo() {
    this.editor.write(this.deletedText);
  }
}

// Invoker — مسؤول عن تنفيذ الأوامر و التراجع
class CommandHistory {
  constructor() {
    this.history = [];
    this.index = -1;
  }

  executeCommand(command) {
    command.execute();
    this.history.push(command);
    this.index++;
  }

  undo() {
    if (this.index < 0) return;
    const command = this.history[this.index];
    command.undo();
    this.index--;
  }

  redo() {
    if (this.index >= this.history.length - 1) return;
    this.index++;
    const command = this.history[this.index];
    command.execute();
  }
}

// الاستخدام
const editor = new TextEditor();
const history = new CommandHistory();

history.executeCommand(new WriteCommand(editor, 'مرحبا '));
history.executeCommand(new WriteCommand(editor, 'بالعالم'));
editor.show(); // 📄 مرحبا بالعالم

history.undo();
editor.show(); // 📄 مرحبا

history.redo();
editor.show(); // 📄 مرحبا بالعالم

تطبيقات أخرى

  • Queue (طابور) — إضافة الأوامر إلى طابور لتنفيذها لاحقًا
  • Macro (ماكرو) — تسجيل سلسلة أوامر لتنفيذها معًا
  • Transactional — تنفيذ مجموعة أوامر مع التراجع الجماعي عند الفشل

متى تستخدمه؟

  • عندما تريد تجسيد الطلبات ككائنات قابلة للتمرير والتخزين
  • عندما تحتاج عمليات Undo/Redo
  • عندما تريد طابور أوامر متأخرة أو مجدولة

⚠️ Command يزيد عدد الكلاسات—كل عملية تحتاج كلاس Command منفصل.

from abc import ABC, abstractmethod

class Command(ABC):
    @abstractmethod
    def execute(self):
        pass

    @abstractmethod
    def undo(self):
        pass

class Editor:
    def __init__(self):
        self.content = ""

    def write(self, text):
        self.content += text

    def delete(self, count):
        deleted = self.content[-count:]
        self.content = self.content[:-count]
        return deleted

class WriteCommand(Command):
    def __init__(self, editor, text):
        self.editor = editor
        self.text = text

    def execute(self):
        self.editor.write(self.text)

    def undo(self):
        self.editor.delete(len(self.text))

editor = Editor()
cmd = WriteCommand(editor, "سلام")
cmd.execute()
print(editor.content)  # سلام
cmd.undo()
print(editor.content)  #

🎯 لقد أكملت مسار OOP → Design Patterns 🎉

شرح نمط Command — أنماط التصميم (Design Patterns) بالعربي
نمط Commandأنماط التصميم (Design Patterns) بالعربي · The Code Fix

📚 لمزيد من التعمّق في أنماط التصميم (Design Patterns)، راجِع البرمجة الكائنية على ويكيبيديا.

هل كان هذا الدرس مفيدًا؟