Menu
Coddy logo textTech

תבנית הפקודה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 94 מתוך 110.

תבנית Command עוטפת בקשה כאובייקט, ומאפשרת לך להגדיר ללקוחות פרמטרים עם בקשות שונות, להוסיף פעולות לתור או לתמוך בפונקציונליות של ביטול. במקום לקרוא ישירות למתודה, עוטפים את הפעולה באובייקט פקודה שאפשר לשמור, להעביר או לבצע מאוחר יותר.

התבנית כוללת שלושה רכיבים מרכזיים: ממשק Command עם מתודת execute, פקודות קונקרטיות שמממשות פעולות ספציפיות, ו-מקבל שמבצע את העבודה בפועל. מפעיל אופציונלי מפעיל פקודות בלי לדעת מה הן עושות:

abstract class Command {
  void execute();
}

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class TurnOffCommand implements Command {
  final Light light;
  TurnOffCommand(this.light);

  @override
  void execute() => light.turnOff();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // האור דולק

  remote.setCommand(TurnOffCommand(light));
  remote.pressButton();  // האור כבוי
}

ה־RemoteControl לא יודע שום דבר על אורות — הוא פשוט מבצע כל פקודה שניתנת לו. הניתוק הזה מקל על הוספת פקודות חדשות בלי לשנות את המפעיל. תבנית Command אידיאלית למימוש מערכות ביטול/ביצוע מחדש, תורי משימות או הקלטת מאקרו, שבהם צריך להתייחס לפעולות כאובייקטים מדרגה ראשונה.

challenge icon

אתגר

קל

בואו נבנה מערכת פקודות לעורך טקסט באמצעות תבנית Command! תיצרו מערכת שעוטפת פעולות טקסט כאובייקטים של פקודות, ומאפשרת לעורך לבצע פעולות שונות בלי לדעת את הפרטים של כל פעולה. זהו שימוש קלאסי בתבנית Command — חשבו על כך כמו על מערכת ביטול/ביצוע מחדש, שבה כל פעולה נשמרת כאובייקט.

תארגנו את הקוד בשני קבצים:

  • commands.dart: צרו כאן את מערכת הפקודות. התחילו במחלקה מופשטת Command שמצהירה על מתודה execute(). לאחר מכן צרו מחלקה TextDocument (המקבל) שמחזיקה שדה String content (ריק בתחילה) ויש לה שלוש מתודות:
    • append(String text) - מוסיפה טקסט לסוף התוכן
    • clear() - מגדירה את התוכן כמחרוזת ריקה
    • show() - מדפיסה Document: [content]
    כעת ממשו שלוש פקודות קונקרטיות שעובדות עם TextDocument:
    • AppendCommand - מקבלת מסמך וטקסט בבנאי שלה, ומוסיפה את הטקסט בעת ביצוע הפקודה
    • ClearCommand - מקבלת מסמך בבנאי שלה, ומנקה אותו בעת ביצוע הפקודה
    • ShowCommand - מקבלת מסמך בבנאי שלה, ומציגה את התוכן שלו בעת ביצוע הפקודה
    לבסוף, צרו מחלקה TextEditor (המפעיל) ששומרת רשימה של פקודות. צריכה להיות לה מתודה addCommand(Command command) להוספת פקודות לתור, ומתודה runAll() שמבצעת את כל הפקודות שבתור לפי הסדר.
  • main.dart: ייבאו את קובץ הפקודות והדגימו את תבנית Command. צרו TextDocument ו-TextEditor. הוסיפו לתור את הפקודות הבאות לפי הסדר: הוסיפו Hello, הוסיפו World, הציגו את המסמך, הוסיפו !, הציגו שוב, נקו את המסמך והציגו אותו בפעם האחרונה. לאחר מכן הריצו את כל הפקודות שבתור.

שימו לב ש-TextEditor לא יודע דבר על הוספה, ניקוי או הצגה — הוא רק מבצע את הפקודות שניתנות לו. ניתוק התלות הזה הוא תמצית תבנית Command!

הפלט הצפוי:

Document: Hello World
Document: Hello World!
Document: 

נסו בעצמכם

import 'commands.dart';

void main() {
  // TODO: צור מופע של TextDocument

  // TODO: צור מופע של TextEditor

  // TODO: הכנס את הפקודות הבאות לתור לפי הסדר:
  // 1. הוסף "Hello"
  // 2. הוסף " World"
  // 3. הצג את המסמך
  // 4. הוסף "!"
  // 5. הצג שוב את המסמך
  // 6. נקה את המסמך
  // 7. הצג את המסמך פעם אחת אחרונה

  // TODO: הרץ את כל הפקודות שבתור
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Dart אונליין