نمط Strategy
جزء من قسم Object Oriented Programming في رحلة Python على Coddy — الدرس 48 من 64.
يُعرف نمط الاستراتيجية (Strategy Pattern) عائلة من الخوارزميات، ويغلف كل واحدة منها، ويجعلها قابلة للتبديل. يمكنك تبديل الخوارزميات في وقت التشغيل دون تغيير كود العميل.
إليك فئات استراتيجية بسيطة لطرق دفع مختلفة:
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) ولكن بسلوك مختلف.
قم بإنشاء فئة سياق (context class) تستخدم الاستراتيجيات:
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)يمكن لفئة السياق (context class) التبديل بين استراتيجيات الدفع المختلفة.
استخدم نمط الاستراتيجية (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())أنشئ مثالاً آخر باستخدام استراتيجيات الفرز:
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 Pattern) تبديل الخوارزميات في وقت التشغيل. قم بتعريف استراتيجيات مختلفة بنفس الواجهة (interface)، ثم اترك فئة السياق (context class) تختار أي واحدة ستستخدم. هذا يجعل كودك مرناً وسهل التوسيع بخوارزميات جديدة دون تغيير الكود الحالي.
التحدي
متوسطقم بتنفيذ استراتيجية BitcoinPayment جديدة لنظام التسوق الخاص بنا.
مهمتك هي:
- إنشاء فئة BitcoinPayment التي تنفذ PaymentStrategy
- يجب أن تقبل wallet_address في المنشئ (constructor)
- يجب أن تطبع طريقة pay بالضبط:
Paying $X using Bitcoin wallet: Yحيث X هو المبلغ و Y هو عنوان المحفظة - يجب أن تعيد طريقة pay القيمة True بعد الطباعة
- كتابة دالة main تقوم بما يلي:
- إنشاء عربة تسوق (shopping cart)
- إضافة كمبيوتر محمول (laptop) بتكلفة $1200 وسماعات رأس (headphones) بتكلفة $100 إلى العربة
- إنشاء BitcoinPayment مع عنوان المحفظة "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
- تعيين استراتيجية الدفع هذه على العربة
- استدعاء طريقة checkout
يتضمن كود البداية بالفعل if __name__ == "__main__": في الأسفل — لست بحاجة لإضافتها بنفسك. هذا عرف في لغة Python يضمن أن دالة main() الخاصة بك تعمل فقط عند تنفيذ الملف مباشرة (وليس عند استيراده بواسطة وحدة أخرى). ببساطة قم بتعريف دالة main() وسيقوم المربع البرمجي المقدم باستدعائها تلقائياً.
اتبع نفس الهيكل الموضح في أمثلة الدرس.
ورقة مرجعية
يحدد نمط الاستراتيجية (Strategy Pattern) عائلة من الخوارزميات، ويقوم بتغليف كل منها، ويجعلها قابلة للتبديل. يمكنك تبديل الخوارزميات في وقت التشغيل دون تغيير كود العميل.
قم بإنشاء فئات استراتيجية (strategy classes) بنفس الواجهة:
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"قم بإنشاء فئة سياق (context class) تستخدم الاستراتيجيات:
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)جرّب بنفسك
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()يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكال