Menu
Coddy logo textTech

תבנית Strategy

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

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

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

interface PaymentStrategy {
    void pay(int amount);
}

class CreditCardPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " via Credit Card");
    }
}

class PayPalPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " via PayPal");
    }
}

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

class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}

עכשיו אפשר לשנות את התנהגות התשלום באופן דינמי:

ShoppingCart cart = new ShoppingCart();

cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100);  // שולמו 100 באמצעות כרטיס אשראי

cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50);   // שולמו 50 באמצעות PayPal

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

challenge icon

אתגר

קל

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

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

  • TextFormatter.java: הגדירו את הממשק TextFormatter שכל אסטרטגיות העיצוב יממשו. עליו להצהיר על מתודה יחידה String format(String text) שמקבלת מחרוזת ומחזירה את הגרסה המעוצבת.
  • Formatters.java: צרו שלוש אסטרטגיות קונקרטיות שמממשות את הממשק TextFormatter שלכם:

    UpperCaseFormatter - משנה את הטקסט לאותיות גדולות.

    LowerCaseFormatter - משנה את הטקסט לאותיות קטנות.

    TitleCaseFormatter - הופכת את האות הראשונה בכל מילה לאות גדולה ואת שאר האותיות לאותיות קטנות. מילים מופרדות ברווחים.

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

    שדה פרטי לשמירת אסטרטגיית TextFormatter הנוכחית.

    מתודה setFormatter(TextFormatter formatter) שמשנה את אסטרטגיית העיצוב הפעילה.

    מתודה publishText(String text) שמחילה את המעצב הנוכחי על הטקסט ומדפיסה Published: [formatted text]. אם לא הוגדר מעצב, עליה להדפיס את Published: [original text] ללא שינוי.

  • Main.java: חברו יחד את מערכת האסטרטגיות שלכם! תקבלו שתי קלטים: הטקסט לעיצוב (String) וסגנון העיצוב (String: "upper", "lower" או "title").

    צרו TextEditor וקראו תחילה ל-publishText עם טקסט הקלט, לפני הגדרת מעצב כלשהו (כדי להדגים את התנהגות ברירת המחדל).

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

תקבלו שני קלטים לפי הסדר: הטקסט לעיצוב (String) וסגנון העיצוב (String).

לדוגמה, עבור הקלטים hello world ו-title, הפלט יהיה:

Published: hello world
Published: Hello World

שימו לב שמחלקת TextEditor אינה יודעת דבר על לוגיקת העיצוב הספציפית. היא פשוט מעבירה את המשימה לאסטרטגיה שהוגדרה כרגע. כך קל מאוד להוסיף סגנונות עיצוב חדשים בלי לגעת בקוד של העורך!

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        String style = scanner.nextLine();
        
        // TODO: צור מופע של TextEditor
        
        // TODO: קרא ל-publishText עם טקסט הקלט (לפני הגדרת מעצב כלשהו)
        
        // TODO: בהתאם לקלט הסגנון ("upper", "lower" או "title"),
        // הגדר את המעצב המתאים וקרא שוב ל-publishText
        
    }
}
quiz iconבחנו את עצמכם

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

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

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