Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط Strategy

جزء من قسم البرمجة كائنية التوجه في رحلة Python على Coddy. الدرس 48 من 64.

يحدّد نمط Strategy عائلةً من الخوارزميات، ويغلّف كلّ خوارزمية منها، ويجعلها قابلةً للتبديل. يمكنك تبديل الخوارزميات أثناء وقت التشغيل دون تغيير رمز العميل.

إليك فئات استراتيجية بسيطة لطرق الدفع المختلفة:

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)

يمكن لفئة السياق التبديل بين استراتيجيات الدفع المختلفة.

استخدم نمط strategy pattern:

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())

أنشئ مثالًا آخر باستخدام استراتيجيات sorting:

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]

النقطة الأساسية: يتيح لك نمط Strategy تبديل الخوارزميات أثناء التشغيل. عرّف استراتيجيات مختلفة بالواجهة نفسها، ثم دع فئة السياق تختار أيًّا منها تستخدم. يجعل هذا الشيفرة البرمجية مرنة وسهلة التوسعة بخوارزميات جديدة دون تغيير الشيفرة الموجودة.

challenge icon

التحدي

متوسط

طبّق استراتيجية BitcoinPayment جديدة لنظام shopping الخاص بنا.

مهمتك هي:

  1. إنشاء فئة BitcoinPayment تطبّق PaymentStrategy
    • يجب أن تقبل wallet_address في المُنشئ
    • يجب أن تطبع طريقة pay النص التالي تمامًا: Paying $X using Bitcoin wallet: Y حيث يمثّل X المبلغ ويمثّل Y عنوان المحفظة
    • يجب أن تعيد طريقة pay القيمة True بعد الطباعة
  2. كتابة دالة main التي:
    • تنشئ عربة shopping
    • تضيف حاسوبًا محمولًا بتكلفة $1200 وسماعات بتكلفة $100 إلى العربة
    • تنشئ BitcoinPayment باستخدام عنوان المحفظة "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
    • تعيّن استراتيجية payment هذه للعربة
    • تستدعي طريقة 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")

# Create your BitcoinPayment strategy class here


if __name__ == "__main__":
    main()
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Python عبر الإنترنت