Menu
Coddy logo textTech

תבנית Strategy

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Python של Coddy. שיעור 48 מתוך 64.

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

הנה מחלקות אסטרטגיה פשוטות לשיטות תשלום שונות:

class CreditCard:
    def pay(self, amount):
        return f"Paid ${amount} with Credit Card"

class PayPal:
    def pay(self, amount):
        return f"Paid ${amount} with PayPal"

class Bitcoin:
    def pay(self, amount):
        return f"Paid ${amount} with Bitcoin"

כל אסטרטגיה מממשת את אותה השיטה (pay), אך עם התנהגות שונה.

צרו מחלקת הקשר שמשתמשת באסטרטגיות:

class ShoppingCart:
    def __init__(self):
        self.total = 0
        self.payment_strategy = None
    
    def add_item(self, price):
        self.total += price
    
    def set_payment_strategy(self, strategy):
        self.payment_strategy = strategy
    
    def checkout(self):
        return self.payment_strategy.pay(self.total)

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

השתמשו בתבנית האסטרטגיה:

cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)

# השתמש באסטרטגיית תשלום בכרטיס אשראי
cart.set_payment_strategy(CreditCard())
print(cart.checkout())

# עבור לאסטרטגיית PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())

צרו דוגמה נוספת עם אסטרטגיות מיון:

class BubbleSort:
    def sort(self, data):
        return f"Bubble sorted: {sorted(data)}"

class QuickSort:
    def sort(self, data):
        return f"Quick sorted: {sorted(data)}"

class Sorter:
    def __init__(self, strategy):
        self.strategy = strategy
    
    def set_strategy(self, strategy):
        self.strategy = strategy
    
    def sort_data(self, data):
        return self.strategy.sort(data)

# השתמשו באסטרטגיות מיון שונות
numbers = [3, 1, 4, 1, 5]

sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))

sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))

פלט:

Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]

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

challenge icon

אתגר

בינוני

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

המשימה שלכם:

  1. ליצור מחלקה בשם BitcoinPayment שמממשת את PaymentStrategy
    • המחלקה צריכה לקבל wallet_address בבנאי
    • המתודה pay צריכה להדפיס בדיוק: Paying $X using Bitcoin wallet: Y כאשר X הוא הסכום ו-Y היא כתובת הארנק
    • המתודה pay צריכה להחזיר True לאחר ההדפסה
  2. לכתוב פונקציה בשם main ש:
    • יוצרת עגלת קניות
    • מוסיפה לעגלה מחשב נייד שעולה $1200 ואוזניות שעולות $100
    • יוצרת BitcoinPayment עם כתובת הארנק "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
    • מגדירה את אסטרטגיית התשלום הזו בעגלה
    • קוראת למתודה checkout

קוד הפתיחה כבר כולל את if __name__ == "__main__": בתחתית. אין צורך להוסיף אותו בעצמכם. זו מוסכמה של Python שמבטיחה שהפונקציה main() תפעל רק כשהקובץ מופעל ישירות (ולא כשהוא מיובא על ידי מודול אחר). פשוט הגדירו את הפונקציה main(), והבלוק שסופק יקרא לה באופן אוטומטי.

פעלו לפי אותו מבנה שמוצג בדוגמאות השיעור.

נסו בעצמכם

from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number, expiry_date, cvv):
        self.card_number = card_number
        self.expiry_date = expiry_date
        self.cvv = cvv
        
    def pay(self, amount):
        print(f"Paying ${amount} using Credit Card: {self.card_number}")
        return True

class PayPalPayment(PaymentStrategy):
    def __init__(self, email, password):
        self.email = email
        self.password = password
        
    def pay(self, amount):
        print(f"Paying ${amount} using PayPal account: {self.email}")
        return True

class ShoppingCart:
    def __init__(self):
        self.items = []
        self.payment_strategy = None
    
    def add_item(self, item, price):
        self.items.append({"item": item, "price": price})
    
    def set_payment_strategy(self, payment_strategy):
        self.payment_strategy = payment_strategy
    
    def checkout(self):
        total = sum(item["price"] for item in self.items)
        if self.payment_strategy:
            return self.payment_strategy.pay(total)
        else:
            raise ValueError("No payment strategy set")

# צרו כאן את מחלקת אסטרטגיית התשלום BitcoinPayment


if __name__ == "__main__":
    main()
quiz iconבחנו את עצמכם

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

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

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