Menu
CoddyTech

نمط 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 عبر الإنترنت