Menu
Coddy logo textTech

תבנית האסטרטגיה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 55 מתוך 70.

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

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

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

ההקשר (ShoppingCart) לא יודע באיזו שיטת תשלום הוא משתמש — הוא פשוט קורא ל־Pay() באסטרטגיה שסופקה:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // שולם 99.99 באמצעות כרטיס אשראי

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // שולם 49.99 באמצעות PayPal

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

challenge icon

אתגר

קל

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

תארגנו את הקוד שלכם בשלושה קבצים:

  • ShippingStrategy.cs: הגדירו ממשק IShippingStrategy במרחב השמות Shipping, עם מתודה CalculateCost(double weight) שמחזירה double. לאחר מכן צרו שלוש מחלקות אסטרטגיה קונקרטיות:
    • StandardShipping - מחשבת את העלות כך: weight * 1.5
    • ExpressShipping - מחשבת את העלות כך: weight * 3.0 + 5.0 (כולל עמלת משלוח מהיר קבועה)
    • OvernightShipping - מחשבת את העלות כך: weight * 5.0 + 10.0 (שירות פרימיום עם עמלת בסיס גבוהה יותר)
  • OrderProcessor.cs: צרו מחלקה בשם OrderProcessor באותו מרחב שמות. זוהי מחלקת ההקשר שלכם, שמשתמשת באסטרטגיית משלוח. היא צריכה לכלול:
    • שדה פרטי שיחזיק את ה-IShippingStrategy הנוכחי
    • מתודה SetShippingMethod(IShippingStrategy strategy) לשינוי אסטרטגיית המשלוח
    • מתודה ProcessOrder(double weight) שמשתמשת באסטרטגיה הנוכחית כדי לחשב ולהחזיר את עלות המשלוח
  • Program.cs: חברו את כל החלקים באמצעות יצירת OrderProcessor והדגמה של החלפת אסטרטגיות משלוח בזמן ריצה. אותו מעבד יכול לחשב עלויות באמצעות אלגוריתמים שונים, פשוט על ידי שינוי האסטרטגיה שלו.

תקבלו שתי קלטים:

  • סוג שיטת המשלוח: standard, express או overnight
  • משקל החבילה כמספר עשרוני (לדוגמה, 4.5)

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

לדוגמה, אם הקלט הוא express ו-4.5, הפלט צריך להיות:

18.5

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

נסו בעצמכם

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // קרא את הקלט
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: צור מופע של OrderProcessor

        // TODO: בהתאם ל-shippingType ("standard", "express" או "overnight"),
        // צור את אסטרטגיית המשלוח המתאימה והגדר אותה במעבד

        // TODO: עבד את ההזמנה והדפס את העלות המחושבת
    }
}
quiz iconבחנו את עצמכם

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

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

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