Menu
Coddy logo textTech

תבנית שיטת התבנית

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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() לפי הצורך. היתרון המרכזי הוא שמבנה האלגוריתם נשאר עקבי בכל המימושים, תוך מתן גמישות בשלבים הבודדים.

challenge icon

אתגר

קל

בואו נבנה מערכת ליצירת דוחות באמצעות תבנית 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() שלו
}
quiz iconבחנו את עצמכם

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

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

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