Menu
Coddy logo textTech

תבנית הפקודה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 56 מתוך 70.

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

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

public interface ICommand
{
    void Execute();
}

public class Light  // מקבל
{
    public void TurnOn() => Console.WriteLine("Light is ON");
    public void TurnOff() => Console.WriteLine("Light is OFF");
}

public class TurnOnCommand : ICommand
{
    private Light _light;
    
    public TurnOnCommand(Light light) => _light = light;
    
    public void Execute() => _light.TurnOn();
}

public class TurnOffCommand : ICommand
{
    private Light _light;
    
    public TurnOffCommand(Light light) => _light = light;
    
    public void Execute() => _light.TurnOff();
}

המפעיל מאחסן ומבצע פקודות בלי לדעת מה הן עושות:

public class RemoteControl  // מפעיל
{
    private ICommand _command;
    
    public void SetCommand(ICommand command) => _command = command;
    
    public void PressButton() => _command.Execute();
}

// שימוש
var light = new Light();
var remote = new RemoteControl();

remote.SetCommand(new TurnOnCommand(light));
remote.PressButton();  // Light דולק (ON)

remote.SetCommand(new TurnOffCommand(light));
remote.PressButton();  // Light כבוי (OFF)

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

challenge icon

אתגר

קל

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

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

  • Command.cs: הגדירו ממשק ICommand במרחב השמות TextEditor עם שיטה אחת, Execute(). לאחר מכן צרו שתי מחלקות פקודה קונקרטיות:
    • InsertCommand - מקבלת Document ומחרוזת text בבנאי שלה. בעת ביצוע הפקודה, היא מוסיפה את הטקסט למסמך ומדפיסה Inserted: {text}
    • DeleteCommand - מקבלת Document ו-int count בבנאי שלה. בעת ביצוע הפקודה, היא מסירה את count התווים האחרונים מהמסמך ומדפיסה Deleted: {count} characters
  • Document.cs: צרו מחלקת Document באותו מרחב שמות. זהו המקבל שלכם — האובייקט שמבצע בפועל את פעולות הטקסט. צריכות להיות לה:
    • שדה מחרוזת פרטי לאחסון התוכן (אתחלו אותו למחרוזת ריקה)
    • שיטה Append(string text) שמוסיפה טקסט לתוכן
    • שיטה RemoveLast(int count) שמסירה את count התווים האחרונים (אם count גדול מאורך התוכן, נקו את כל התוכן)
    • שיטה GetContent() שמחזירה את התוכן הנוכחי
  • Program.cs: צרו מחלקת Editor שמשמשת כמפעיל. צריכה להיות לה שיטה SetCommand(ICommand command) ושיטה ExecuteCommand() שמריצה את הפקודה הנוכחית. בקוד הראשי שלכם, הדגימו את תבנית הפקודות באמצעות עיבוד סדרה של פעולות עריכה.

תקבלו את הקלטים הבאים:

  • מספר הפקודות לביצוע
  • עבור כל פקודה: סוג הפקודה (insert או delete) ואחריו הטקסט שיש להוסיף או מספר התווים שיש למחוק

לאחר ביצוע כל הפקודות, הדפיסו את תוכן המסמך הסופי בשורה חדשה בפורמט Content: {content}.

לדוגמה, אם הקלטים הם:

4
insert
Hello
insert
 World
delete
3
insert
!

הפלט צריך להיות:

Inserted: Hello
Inserted:  World
Deleted: 3 characters
Inserted: !
Content: Hello Wo!

שימו לב שה-Editor (המפעיל) אינו יודע דבר על עיבוד טקסט — הוא פשוט מבצע כל פקודה שניתנת לו. הפקודות כוללות בתוכן גם את הפעולה וגם את המקבל, וכך קל להוסיף פעולות חדשות כמו ReplaceCommand בלי לשנות את העורך!

נסו בעצמכם

using System;
using TextEditor;

// TODO: צרו את המחלקה Editor (מפעילת הפקודות)
public class Editor
{
    // TODO: הוסיפו שדה פרטי לשמירת הפקודה הנוכחית
    private ICommand _command;

    // TODO: ממשו את המתודה SetCommand
    public void SetCommand(ICommand command)
    {
        // TODO: שמרו את הפקודה
    }

    // TODO: ממשו את המתודה ExecuteCommand
    public void ExecuteCommand()
    {
        // TODO: בצעו את הפקודה הנוכחית
    }
}

class Program
{
    public static void Main(string[] args)
    {
        // קראו את מספר הפקודות
        int n = Convert.ToInt32(Console.ReadLine());

        // צרו את המסמך (מקבל הפקודות)
        Document document = new Document();

        // צרו את העורך (מפעיל הפקודות)
        Editor editor = new Editor();

        // TODO: עבדו כל פקודה
        for (int i = 0; i < n; i++)
        {
            string commandType = Console.ReadLine();

            // TODO: על סמך commandType, צרו את הפקודה המתאימה
            // - אם "insert": קראו את הטקסט וצרו InsertCommand
            // - אם "delete": קראו את הכמות וצרו DeleteCommand
            // לאחר מכן הגדירו את הפקודה ב-editor והפעילו אותה
        }

        // TODO: הדפיסו את התוכן הסופי בפורמט "Content: {content}"
    }
}
quiz iconבחנו את עצמכם

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

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

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