نمط 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 تبديل الخوارزميات أثناء التشغيل. عرّف استراتيجيات مختلفة بالواجهة نفسها، ثم دع فئة السياق تختار أيًّا منها تستخدم. يجعل هذا الشيفرة البرمجية مرنة وسهلة التوسعة بخوارزميات جديدة دون تغيير الشيفرة الموجودة.
التحدي
متوسططبّق استراتيجية BitcoinPayment جديدة لنظام shopping الخاص بنا.
مهمتك هي:
- إنشاء فئة BitcoinPayment تطبّق PaymentStrategy
- يجب أن تقبل wallet_address في المُنشئ
- يجب أن تطبع طريقة pay النص التالي تمامًا:
Paying $X using Bitcoin wallet: Yحيث يمثّل X المبلغ ويمثّل Y عنوان المحفظة - يجب أن تعيد طريقة pay القيمة True بعد الطباعة
- كتابة دالة 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()يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكالتدرّب بنفسك: مترجم Python عبر الإنترنت