الجزء الأول: الأنماط الإنشائية
4 دقائق قراءة
شرائح الدرس
1 / 14
الغرض: تتعامل هذه الأنماط مع آليات إنشاء الكائنات (Objects)، وتسعى لإنشائها بطريقة تناسب الموقف المطلوب دون تعقيد غير ضروري.
1.1 نمط Singleton
الفكرة الجوهرية: يضمن هذا النمط أن يكون للفئة (Class) نسخة واحدة فقط طوال عمر البرنامج، ويوفّر نقطة وصول عامة إليها من أي مكان في الكود.
classDiagram
class Singleton {
-instance: Singleton
+getInstance(): Singleton
+operation()
}
note for Singleton "Only one instance exists"✅ متى تستخدمه:
- مجمّعات اتصال قواعد البيانات (Database Connection Pools) - لأن إنشاء اتصالات متعددة مكلف
- خدمات تسجيل الأحداث (Logging) - لتجميع السجلات في مكان مركزي واحد
- مديرو الإعدادات (Configuration Managers) - لضمان مصدر واحد للحقيقة (Single Source of Truth)
- تطبيقات التخزين المؤقت (Cache) - لمشاركة مساحة الذاكرة نفسها
- برامج تشغيل الأجهزة (Device Drivers) - للتحكم في الوصول إلى العتاد
مثال بالكود:
class DatabaseConnection:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.connection = None
return cls._instance
def connect(self):
if self.connection is None:
self.connection = "Connected to Database"
print("Database connection established")
return self.connection
# Usage
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True - Same instance1.2 نمط Factory
الفكرة الجوهرية: ينشئ هذا النمط الكائنات دون تحديد فئتها (Class) بشكل صريح ومباشر. تمامًا مثل مصنع سيارات يستطيع إنتاج موديلات مختلفة بناءً على المواصفات المطلوبة، دون أن يحتاج العميل لمعرفة تفاصيل خط الإنتاج.
classDiagram
class AnimalFactory {
+createAnimal(type: String): Animal
}
class Animal {
<<interface>>
+makeSound()
}
class Dog {
+makeSound()
}
class Cat {
+makeSound()
}
AnimalFactory --> Animal
Dog ..|> Animal
Cat ..|> Animal✅ متى تستخدمه:
- عندما لا تعرف الفئة الدقيقة التي ستُنشأ إلا وقت التشغيل (Runtime)
- عندما يكون منطق الإنشاء معقّدًا ويحتاج إلى تمركز في مكان واحد
- عندما تريد فصل عملية إنشاء الكائن عن طريقة استخدامه
- عندما يكون لديك عائلة من المنتجات المترابطة
- عندما تحتاج إلى فرض قيود معينة على عملية الإنشاء
مثال بالكود:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
return "Woof!"
class Cat(Animal):
def make_sound(self):
return "Meow!"
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
if animal_type.lower() == "dog":
return Dog()
elif animal_type.lower() == "cat":
return Cat()
else:
raise ValueError(f"Unknown animal type: {animal_type}")
# Usage
factory = AnimalFactory()
dog = factory.create_animal("dog")
cat = factory.create_animal("cat")
print(dog.make_sound()) # Woof!
print(cat.make_sound()) # Meow!- مثال من الواقع العملي: يُستخدم نمط Factory كثيرًا في أطر عمل واجهات المستخدم الرسومية (GUI Frameworks)، حيث يمكن إنشاء أنواع مختلفة من الأزرار (مثل WindowsButton و MacButton) بناءً على نظام التشغيل المستخدم.
1.3 نمط Builder
الفكرة الجوهرية: يبني هذا النمط الكائنات المعقّدة خطوة بخطوة. تمامًا مثل بناء منزل حيث يمكنك اختيار خيارات مختلفة للغرف والمواد وغيرها، دون الحاجة لتحديد كل شيء دفعة واحدة.
classDiagram
class Pizza {
+size: String
+crust: String
+toppings: List
}
class PizzaBuilder {
-pizza: Pizza
+setSize(size: String): PizzaBuilder
+setCrust(crust: String): PizzaBuilder
+addTopping(topping: String): PizzaBuilder
+build(): Pizza
}
class Director {
+makeMargherita(): Pizza
+makePepperoni(): Pizza
}
Director --> PizzaBuilder
PizzaBuilder --> Pizza✅ متى تستخدمه:
- عند إنشاء كائنات لها عدد كبير من المعاملات الاختيارية (أكثر من 4-5 معاملات)
- عندما يصبح الـ Constructor مثقلًا بعدد كبير جدًا من المعاملات
- عندما تريد إنشاء تمثيلات مختلفة للكائن نفسه
- عندما تكون عملية الإنشاء معقّدة وتتم على عدة مراحل
- عندما تحتاج إلى كائنات غير قابلة للتغيير (Immutable) وتحتوي على حقول كثيرة
مثال بالكود:
class Pizza:
def __init__(self):
self.size = None
self.crust = None
self.toppings = []
def __str__(self):
return f"{self.size} {self.crust} pizza with {', '.join(self.toppings)}"
class PizzaBuilder:
def __init__(self):
self.pizza = Pizza()
def set_size(self, size):
self.pizza.size = size
return self
def set_crust(self, crust):
self.pizza.crust = crust
return self
def add_topping(self, topping):
self.pizza.toppings.append(topping)
return self
def build(self):
return self.pizza
# Usage
pizza = (PizzaBuilder()
.set_size("Large")
.set_crust("Thin")
.add_topping("Pepperoni")
.add_topping("Mushrooms")
.build())
print(pizza) # Large Thin pizza with Pepperoni, Mushrooms