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