Menu
Coddy logo textTech

תבנית המתודה התבניתית

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 73 מתוך 87.

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

התבנית משתמשת במחלקה מופשטת עם מתודת תבנית שקוראת לרצף של שלבים. לחלק מהשלבים יש מימושי ברירת מחדל, בעוד שאחרים מופשטים וחייבים להיות ממומשים במחלקות יורשות:

abstract class DataProcessor {
    // מתודת תבנית - מגדירה את מבנה האלגוריתם
    public final void process() {
        readData();
        processData();
        saveData();
    }
    
    abstract void readData();
    abstract void processData();
    
    // מימוש ברירת מחדל (מתודת עוגן)
    void saveData() {
        System.out.println("Saving to default location");
    }
}

class CSVProcessor extends DataProcessor {
    void readData() {
        System.out.println("Reading CSV file");
    }
    
    void processData() {
        System.out.println("Parsing CSV data");
    }
}

class XMLProcessor extends DataProcessor {
    void readData() {
        System.out.println("Reading XML file");
    }
    
    void processData() {
        System.out.println("Parsing XML data");
    }
}

בדרך כלל מסמנים את שיטת התבנית כ־final כדי למנוע ממחלקות משנה לשנות את מבנה האלגוריתם. כשקוראים לה, היא מבצעת את אותו רצף עבור כל מחלקות המשנה:

DataProcessor csv = new CSVProcessor();
csv.process();
// פלט:
// קורא קובץ CSV
// מנתח נתוני CSV
// שומר במיקום ברירת המחדל

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

challenge icon

אתגר

קל

בואו נבנה מערכת ליצירת מסמכים באמצעות תבנית השיטה (Template Method Pattern)! תיצרו מסגרת שבה סוגי מסמכים שונים (דוחות וחשבוניות) פועלים לפי אותו תהליך יצירה, אך מתאימים אישית שלבים מסוימים. זה מושלם למצבים שבהם תהליך העבודה הכללי קבוע, אך הפרטים משתנים בהתאם לסוג המסמך.

תארגנו את הקוד בארבעה קבצים:

  • DocumentGenerator.java: צרו מחלקת בסיס אבסטרקטית שמגדירה את תבנית השיטה. למחלקה DocumentGenerator צריכים להיות:

    שיטה final בשם generateDocument() שמגדירה את שלד האלגוריתם באמצעות קריאה לשלושה שלבים לפי הסדר: createHeader(), createBody() ו-createFooter().

    שתי שיטות אבסטרקטיות: createHeader() ו-createBody(), שעל מחלקות הבת לממש.

    שיטת וו createFooter() עם מימוש ברירת מחדל שמדפיס את --- End of Document ---.

  • ReportGenerator.java: צרו מחלקת בת קונקרטית ליצירת דוחות. הבנאי שלה יקבל כותרת לדוח (String).

    השיטה createHeader() מדפיסה את === REPORT: [title] ===

    השיטה createBody() מדפיסה את Report content goes here...

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

  • InvoiceGenerator.java: צרו מחלקת בת קונקרטית נוספת ליצירת חשבוניות. הבנאי שלה יקבל שם לקוח (String) וסכום (double).

    השיטה createHeader() מדפיסה את *** INVOICE ***

    השיטה createBody() מדפיסה בשורה אחת את Customer: [name], ולאחר מכן בשורה הבאה את Amount Due: $[amount] (עצבו את הסכום כך שיוצגו שתי ספרות אחרי הנקודה העשרונית).

    דרסו את createFooter() כדי להדפיס את Thank you for your business!

  • Main.java: חברו יחד את מערכת תבנית השיטה! תקבלו שלוש קלטים: כותרת לדוח (String), שם לקוח (String) וסכום חשבונית (double).

    צרו ReportGenerator עם הכותרת וקראו ל-generateDocument(). הדפיסו שורה ריקה להפרדה. לאחר מכן, צרו InvoiceGenerator עם שם הלקוח והסכום, וקראו ל-generateDocument().

תקבלו שלוש קלטים לפי הסדר: כותרת לדוח (String), שם לקוח (String) וסכום חשבונית (double).

לדוגמה, עבור הקלטים Q4 Sales, Acme Corp ו-1500.00, הפלט שלכם יהיה:

=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---

*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!

שימו לב ששני סוגי המסמכים פועלים לפי אותו תהליך בן שלושה שלבים שמוגדר בתבנית השיטה, אך כל אחד מהם מתאים את השלבים באופן שונה. ה-ReportGenerator משתמש בכותרת התחתונה שמוגדרת כברירת מחדל, בעוד שה-InvoiceGenerator מספק כותרת תחתונה משלו. זהו הכוח של שיטות וו בתבנית השיטה!

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קראו את נתוני הקלט
        String reportTitle = scanner.nextLine();
        String customerName = scanner.nextLine();
        double invoiceAmount = scanner.nextDouble();
        
        // TODO: צרו ReportGenerator עם הכותרת וקראו ל-generateDocument()
        
        // TODO: הדפיסו שורה ריקה להפרדה
        
        // TODO: צרו InvoiceGenerator עם שם הלקוח והסכום, וקראו ל-generateDocument()
        
    }
}
quiz iconבחנו את עצמכם

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

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

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