תבנית המתודה התבניתית
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 59 מתוך 70.
תבנית שיטת התבנית היא תבנית התנהגותית שמגדירה את השלד של אלגוריתם במחלקת בסיס, ומאפשרת למחלקות יורשות לדרוס שלבים מסוימים בלי לשנות את המבנה הכולל. מחלקת הבסיס שולטת בזרימת העבודה, בעוד שמחלקות נגזרות מתאימות אישית חלקים בודדים.
התבנית הזאת משתמשת בירושה ובמתודות מופשטות. מחלקת הבסיס מכילה ״מתודת תבנית״ הקוראת לרצף של שלבים, שחלקם מופשטים ויש לממש אותם במחלקות־בת:
public abstract class DataProcessor
{
// מתודת תבנית - מגדירה את מבנה האלגוריתם
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}
public class CsvProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading CSV file");
protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading JSON file");
protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
protected override void SaveData() => Console.WriteLine("Saving to cloud");
}כל תת־מחלקה מספקת מימוש משלה, בעוד שמחלקת הבסיס אוכפת את סדר הפעולות:
DataProcessor csv = new CsvProcessor();
csv.Process();
// קריאת קובץ CSV
// ניתוח נתוני CSV
// שמירה במיקום ברירת המחדל
DataProcessor json = new JsonProcessor();
json.Process();
// קריאת קובץ JSON
// ניתוח נתוני JSON
// שמירה בענןתבנית Template Method אידיאלית כשכמה מחלקות חולקות את אותו מבנה אלגוריתם, אך נבדלות בשלבים מסוימים. היא מעודדת שימוש חוזר בקוד על ידי הצבת הלוגיקה המשותפת במחלקת הבסיס, תוך מתן גמישות באמצעות מתודות שניתן לדרוס.
אתגר
קלבואו נבנה מערכת ליצירת דוחות באמצעות תבנית Template Method. סוגים שונים של דוחות (כמו דוחות מכירות ודוחות מלאי) חולקים את אותו מבנה כללי — כולם צריכים לאסוף נתונים, לעצב אותם ולהפיק את התוצאה — אבל כל סוג דוח מטפל בשלבים האלה באופן שונה.
תארגנו את הקוד שלכם בשלושה קבצים:
ReportGenerator.cs: צרו מחלקה מופשטתReportGeneratorבמרחב השמותReporting. מחלקת הבסיס הזו מגדירה את השלד של האלגוריתם ליצירת דוחות באמצעות שיטת תבנית בשםGenerate(). השיטה צריכה לקרוא לשלושה שלבים לפי הסדר:GatherData(),FormatReport()ו-OutputReport(). הגדירו אתGatherData()ואתFormatReport()כמופשטות (כל סוג דוח יממש אותן באופן שונה), ואילוOutputReport()צריכה להיות שיטה וירטואלית עם מימוש ברירת מחדל שמדפיסSending to default printer.ConcreteReports.cs: צרו שתי מחלקות דוח קונקרטיות באותו מרחב שמות, שיורשות מ-ReportGenerator:SalesReport— מממשת אתGatherData()כך שתדפיסCollecting sales data from database, ואתFormatReport()כך שתדפיסFormatting as sales summaryInventoryReport— מממשת אתGatherData()כך שתדפיסScanning warehouse inventory, אתFormatReport()כך שתדפיסFormatting as inventory list, ודורסת אתOutputReport()כך שתדפיסSending to warehouse manager
Program.cs: חברו את הכול על ידי יצירת מופעי דוחות והפקתם. שיטת התבנית מבטיחה שכל דוח יפעל לפי אותו תהליך בן שלושה שלבים, אך ההתנהגות המסוימת של כל שלב משתנה בהתאם לסוג הדוח.
תקבלו קלט אחד:
- סוג הדוח:
salesאוinventory
צרו את מחולל הדוחות המתאים על סמך הקלט וקראו לשיטה Generate() שלו.
לדוגמה, אם הקלט הוא sales, הפלט צריך להיות:
Collecting sales data from database
Formatting as sales summary
Sending to default printerאם הקלט הוא inventory, הפלט צריך להיות:
Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse managerשימו לב ששני הדוחות פועלים לפי אותו מבנה אלגוריתם בדיוק (איסוף, עיצוב, הפקה), אך המימוש של כל שלב מותאם אישית. SalesReport משתמשת בהתנהגות ברירת המחדל של ההפקה, ואילו InventoryReport דורסת אותה — וכך מודגם כיצד תבנית Template Method מאפשרת לכם לקבוע אילו שלבים חובה לדרוס ואילו ניתן להתאים באופן אופציונלי!
נסו בעצמכם
using System;
using Reporting;
class Program
{
public static void Main(string[] args)
{
string reportType = Console.ReadLine();
// TODO: צרו את מחולל הדוחות המתאים בהתאם ל-reportType
// אם reportType הוא "sales", צרו SalesReport
// אם reportType הוא "inventory", צרו InventoryReport
// לאחר מכן, קראו למתודה Generate() על הדוח
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין