תבנית שיטת התבנית
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 97 מתוך 110.
תבנית Template Method מגדירה את השלד של אלגוריתם במחלקת בסיס, ומאפשרת למחלקות יורשות לשנות שלבים מסוימים בלי לשנות את המבנה הכללי. מחלקת הבסיס שולטת בתהליך העבודה, ואילו המחלקות היורשות מתאימות אישית שלבים בודדים.
התבנית הזו משתמשת בירושה: מחלקה מופשטת מגדירה מתודת תבנית שקוראת לרצף של שלבים, שחלקם מופשטים (חייבים להיות ממומשים במחלקות משנה) ולחלקם יש מימושים כברירת מחדל:
abstract class DataProcessor {
// מתודת תבנית - מגדירה את מבנה האלגוריתם
void process() {
readData();
processData();
saveData();
}
void readData(); // מופשטת - מחלקות יורשות חייבות לממש
void processData(); // מופשטת - מחלקות יורשות חייבות לממש
void saveData() { // מימוש ברירת מחדל
print('Data saved to database');
}
}
class CsvProcessor extends DataProcessor {
@override
void readData() => print('Reading CSV file');
@override
void processData() => print('Parsing CSV rows');
}
class JsonProcessor extends DataProcessor {
@override
void readData() => print('Reading JSON file');
@override
void processData() => print('Parsing JSON objects');
@override
void saveData() => print('Saved to cloud storage');
}
void main() {
var csv = CsvProcessor();
csv.process();
// קריאת קובץ CSV
// ניתוח שורות CSV
// הנתונים נשמרו במסד הנתונים
var json = JsonProcessor();
json.process();
// קריאת קובץ JSON
// ניתוח אובייקטים של JSON
// נשמר באחסון בענן
}השיטה process() היא התבנית — היא מגדירה את סדר הפעולות. מחלקות יורשות מממשות את readData() ואת processData() באופן שונה, ויכולות לדרוס את saveData() לפי הצורך. היתרון המרכזי הוא שמבנה האלגוריתם נשאר עקבי בכל המימושים, תוך מתן גמישות בשלבים הבודדים.
אתגר
קלבואו נבנה מערכת ליצירת דוחות באמצעות תבנית Template Method! תיצרו מסגרת שבה סוגים שונים של דוחות פועלים לפי אותו מבנה כללי, אך כל סוג של דוח מתאים אישית שלבים מסוימים, כמו איסוף נתונים ועיצוב הפלט.
תארגנו את הקוד בשני קבצים:
report_generator.dart: הקובץ הזה מכיל את מחלקת הבסיס האבסטרקטית ואת המימושים הקונקרטיים של הדוחות. צרו מחלקה אבסטרקטית בשםReportGeneratorעם מתודת תבנית בשםgenerate(), שמגדירה את תהליך העבודה ליצירת הדוח לפי הסדר הבא:fetchData(),analyzeData(),formatReport()ו-deliver(). המתודותfetchData()ו-formatReport()צריכות להיות אבסטרקטיות (כל סוג של דוח מטפל בהן בצורה שונה), ואילוanalyzeData()צריכה להדפיסAnalyzing data...ו-deliver()צריכה להדפיסReport delivered via email.כמימושי ברירת מחדל. לאחר מכן, צרו שתי מחלקות קונקרטיות של דוחות:SalesReport— המתודהfetchData()שלה מדפיסהFetching sales data from database..., והמתודהformatReport()שלה מדפיסהFormatting as bar charts and tables.InventoryReport— המתודהfetchData()שלה מדפיסהFetching inventory levels from warehouse..., המתודהformatReport()שלה מדפיסהFormatting as inventory list., והיא דורסת אתdeliver()כדי להדפיסReport sent to warehouse manager.
main.dart: ייבאו את קובץ מחולל הדוחות והדגימו כיצד תבנית Template Method שומרת על מבנה אלגוריתם עקבי, תוך מתן אפשרות להתאמה אישית. צרוSalesReportוקראו למתודהgenerate()שלו. לאחר מכן, הדפיסו שורה ריקה להפרדה. צרו גםInventoryReportוקראו למתודהgenerate()שלו.
שימו לב ששני הדוחות פועלים לפי אותו תהליך בן ארבעה שלבים, אך כל אחד מהם מתאים אישית את השלבים החשובים למטרה הספציפית שלו. InventoryReport אפילו דורס את מתודת ברירת המחדל למסירת הדוח כדי לשלוח דוחות לנמען אחר!
הפלט הצפוי:
Fetching sales data from database...
Analyzing data...
Formatting as bar charts and tables.
Report delivered via email.
Fetching inventory levels from warehouse...
Analyzing data...
Formatting as inventory list.
Report sent to warehouse manager.נסו בעצמכם
import 'report_generator.dart';
void main() {
// TODO: צרו SalesReport וקראו למתודה generate() שלו
// TODO: הדפיסו שורה ריקה להפרדה
// TODO: צרו InventoryReport וקראו למתודה generate() שלו
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
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 אונליין