תבנית הפקודה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 אידיאלית למימוש מערכות ביטול/ביצוע מחדש, תורי משימות או הקלטת מאקרו, שבהם צריך להתייחס לפעולות כאובייקטים מדרגה ראשונה.
אתגר
קלבואו נבנה מערכת פקודות לעורך טקסט באמצעות תבנית 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: הרץ את כל הפקודות שבתור
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםספריות וייבואמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותמשתני מופעיסודות הבנאיחזרה: מחשבון פשוט4בטיחות מפני ערכי null
מבוא לבטיחות מפני ערכי nullניתן להקצאה ל-null לעומת לא ניתן להקצאה ל-nullהאופרטורים ? ו-!מילת המפתח Late ובטיחות מפני ערכי nullאופרטורים מודעי nullבטיחות מפני ערכי null במחלקותסיכום – מערכת פרופילי משתמשים7מחלקות מופשטות וממשקים
מחלקות מופשטותמתודות מופשטותממשקים ב-Dartממשקים משתמעיםמימוש לעומת הורשהממשקים מרוביםחזרה – מחשבון צורות10אוספים וגנריות
סקירה כללית של List, Set ו-Mapאוספים בטוחים מבחינת טיפוסיםמחלקות גנריותמתודות גנריותאילוצים גנרייםIterable ו-Iteratorסיכום – אחסון גנרי13מושגי OOP מתקדמים
הרכבה לעומת הורשהמתודות הרחבהמחלקות קריאותמחלקות אטומות (Dart 3)רשומות (Dart 3)תבניות והתאמה (3.0)טיפוסים מונים עם מתודות16פרויקט: ניהול ספרייה
סקירת הפרויקטמחלקות ספר ומשתמש2בנאים ב-Dart
בנאי ברירת מחדלבנאים בעלי שםרשימות אתחולבנאים קבועיםבנאי Factoryבנאים מפניםסיכום - בונה צורות5כימוס
חברים ציבוריים לעומת פרטייםמוסכמת הקידומת _פרטיות ברמת הספרייההעמקה ב-getters וב-settersהסתרת מידעסיכום – רשומות תלמידים8מיקסינים
מבוא למיקסיניםיצירת מיקסיניםשימוש במספר מיקסיניםמילת המפתח on במיקסיניםמיקסינים לעומת ירושהמיקסינים לעומת ממשקסיכום – מערכת בעלי החיים3מאפייני מחלקה
איברי מופע לעומת איברים סטטייםשדות final ו-constמשתני lateמתודות ושדות סטטייםGetters ו-Settersסיכום – מנהל חשבונות בנק6ירושה
ירושה בסיסיתמילת המפתח superדריסת מתודותהאנוטציה @overrideמילת המפתח final למחלקהבנאים וירושהסיכום – היררכיית עובדים9פולימורפיזם
יסודות הפולימורפיזםפולימורפיזם באמצעות ממשקיםבדיקת טיפוסים בזמן ריצההאופרטורים is ו-asמילת המפתח קווריאנטיסיכום — מעבד תשלומים12תכנות מונחה עצמים אסינכרוני
Future-ים ו-async/awaitיסודות ה-Streamsבקרי Streamsבנאים אסינכרונייםאסינכרוניות במתודות של מחלקהסיכום - אחזור נתונים15תבניות עיצוב חלק 2
תבנית הפקודהתבנית המתאםתבנית העיצובןתבנית שיטת התבניתתבנית המצבתבנית המרוכבתבנית המאגרתרגלו בעצמכם: קומפיילר Dart אונליין