الجزء الثالث: الأنماط السلوكية
2 دقيقتان قراءة
شرائح الدرس
1 / 13
الغرض: تركّز هذه الأنماط على التواصل بين الكائنات وتوزيع المسؤوليات بينها.
3.1 نمط Observer
الفكرة الجوهرية: يعرّف هذا النمط علاقة اعتماد من واحد إلى كثير (One-to-Many)، بحيث عندما يتغيّر حال كائن واحد، تُخطَر كل الكائنات المعتمِدة عليه تلقائيًا. تمامًا مثل نظام الاشتراك في نشرة بريدية.
classDiagram
class Subject {
-observers: List~Observer~
+attach(observer: Observer)
+detach(observer: Observer)
+notify()
}
class Observer {
<<interface>>
+update(data)
}
class ConcreteSubject {
-state
+getState()
+setState(state)
}
class ConcreteObserverA {
+update(data)
}
class ConcreteObserverB {
+update(data)
}
Subject <|-- ConcreteSubject
Observer <|.. ConcreteObserverA
Observer <|.. ConcreteObserverB
Subject --> Observer✅ متى تستخدمه:
- أنظمة معالجة الأحداث (واجهات المستخدم الرسومية، تفاعلات المستخدم)
- بنية Model-View المعمارية (مثل MVC وMVP وMVVM)
- عندما تتطلب التغييرات في كائن واحد تحديث عدة كائنات أخرى
- تنفيذ معالجة الأحداث الموزّعة
- التحديثات اللحظية للبيانات (أسعار الأسهم، خلاصات الأخبار)
مثال بالكود:
from abc import ABC, abstractmethod
class Observer(ABC):
@abstractmethod
def update(self, message):
pass
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
class WeatherStation(Subject):
def __init__(self):
super().__init__()
self._temperature = 0
@property
def temperature(self):
return self._temperature
@temperature.setter
def temperature(self, temp):
self._temperature = temp
self.notify(f"Temperature changed to {temp}°C")
class Display(Observer):
def __init__(self, name):
self.name = name
def update(self, message):
print(f"{self.name} received: {message}")
# Usage
weather_station = WeatherStation()
phone_display = Display("Phone")
computer_display = Display("Computer")
weather_station.attach(phone_display)
weather_station.attach(computer_display)
weather_station.temperature = 25 # Both displays get notified
weather_station.temperature = 30 # Both displays get notified again3.2 نمط Strategy
الفكرة الجوهرية: يعرّف هذا النمط عائلة من الخوارزميات، ويغلّف كل واحدة منها على حدة، ويجعلها قابلة للتبديل فيما بينها. تمامًا مثل اختيار طرق مختلفة للوصول إلى الوجهة نفسها.
classDiagram
class Context {
-strategy: Strategy
+setStrategy(strategy: Strategy)
+executeStrategy()
}
class Strategy {
<<interface>>
+execute()
}
class ConcreteStrategyA {
+execute()
}
class ConcreteStrategyB {
+execute()
}
class ConcreteStrategyC {
+execute()
}
Context --> Strategy
Strategy <|.. ConcreteStrategyA
Strategy <|.. ConcreteStrategyB
Strategy <|.. ConcreteStrategyC✅ متى تستخدمه:
- وجود عدة طرق لتنفيذ المهمة نفسها
- تجنّب جمل الشرط الطويلة (Conditional Statements) عند اختيار الخوارزمية
- تبديل الخوارزمية وقت التشغيل بناءً على الشروط
- عندما يكون للخوارزميات خصائص أداء مختلفة
- بنى الإضافات (Plugin Architectures) حيث يمكن تبديل السلوك
مثال بالكود:
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardPayment(PaymentStrategy):
def __init__(self, card_number):
self.card_number = card_number
def pay(self, amount):
return f"Paid ${amount} using Credit Card ending in {self.card_number[-4:]}"
class PayPalPayment(PaymentStrategy):
def __init__(self, email):
self.email = email
def pay(self, amount):
return f"Paid ${amount} using PayPal account {self.email}"
class CryptoPayment(PaymentStrategy):
def __init__(self, wallet_address):
self.wallet_address = wallet_address
def pay(self, amount):
return f"Paid ${amount} using Crypto wallet {self.wallet_address[:8]}..."
class ShoppingCart:
def __init__(self):
self.items = []
self.payment_strategy = None
def add_item(self, item, price):
self.items.append((item, price))
def set_payment_strategy(self, strategy):
self.payment_strategy = strategy
def checkout(self):
total = sum(price for item, price in self.items)
if self.payment_strategy:
return self.payment_strategy.pay(total)
return "No payment method selected"
# Usage
cart = ShoppingCart()
cart.add_item("Laptop", 1000)
cart.add_item("Mouse", 25)
# Try different payment strategies
credit_card = CreditCardPayment("1234567890123456")
paypal = PayPalPayment("[email protected]")
cart.set_payment_strategy(credit_card)
print(cart.checkout()) # Paid $1025 using Credit Card ending in 3456
cart.set_payment_strategy(paypal)
print(cart.checkout()) # Paid $1025 using PayPal account [email protected]3.3 نمط Command
الفكرة الجوهرية: يغلّف هذا النمط طلبًا (Request) في صورة كائن مستقل، مما يتيح لك تزويد العملاء بطلبات مختلفة، وترتيب العمليات في طابور تنفيذ، ودعم خاصية التراجع (Undo). تمامًا مثل ريموت كنترول له أزرار مختلفة لكل مهمة.
classDiagram
class Invoker {
-command: Command
+setCommand(command: Command)
+executeCommand()
}
class Command {
<<interface>>
+execute()
+undo()
}
class ConcreteCommand {
-receiver: Receiver
-state
+execute()
+undo()
}
class Receiver {
+action()
}
class Client {
+main()
}
Invoker --> Command
Command <|.. ConcreteCommand
ConcreteCommand --> Receiver
Client --> ConcreteCommand
Client --> Receiver
Client --> Invoker✅ متى تستخدمه:
- وظائف التراجع/الإعادة (Undo/Redo) في التطبيقات
- ترتيب العمليات في طابور لتنفيذها لاحقًا
- تسجيل ومراجعة العمليات (Logging and Auditing)
- تسجيل وتشغيل الماكرو (Macro Recording and Playback)
- السلوك المعاملاتي (Transactional Behavior) والتراجع الكامل عن العملية
مثال بالكود:
from abc import ABC, abstractmethod
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class Light:
def __init__(self, location):
self.location = location
self.is_on = False
def turn_on(self):
self.is_on = True
return f"{self.location} light is ON"
def turn_off(self):
self.is_on = False
return f"{self.location} light is OFF"
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
return self.light.turn_on()
def undo(self):
return self.light.turn_off()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
return self.light.turn_off()
def undo(self):
return self.light.turn_on()
class RemoteControl:
def __init__(self):
self.commands = {}
self.last_command = None
def set_command(self, slot, command):
self.commands[slot] = command
def press_button(self, slot):
if slot in self.commands:
result = self.commands[slot].execute()
self.last_command = self.commands[slot]
return result
return "No command set for this slot"
def press_undo(self):
if self.last_command:
return self.last_command.undo()
return "No command to undo"
# Usage
living_room_light = Light("Living Room")
bedroom_light = Light("Bedroom")
living_room_on = LightOnCommand(living_room_light)
living_room_off = LightOffCommand(living_room_light)
bedroom_on = LightOnCommand(bedroom_light)
remote = RemoteControl()
remote.set_command(1, living_room_on)
remote.set_command(2, living_room_off)
remote.set_command(3, bedroom_on)
print(remote.press_button(1)) # Living Room light is ON
print(remote.press_button(3)) # Bedroom light is ON
print(remote.press_undo()) # Bedroom light is OFF