تخطَّ إلى المحتوى

🧩 شرح أنماط التصميم (Design Patterns)

مبادئ SOLID — تطبيق عملي

الدرس 16 من 24· ⏱ 5 دقائق قراءة

مقدمة

SOLID هي خمسة مبادئ أساسية في التصميم كائني التوجّه. كل حرف يرمز لمبدأ يساعدك في بناء كود قابل للصيانة والتوسّع.

S — Single Responsibility Principle (SRP)

لكل كلاس سبب واحد فقط للتغيير.

// ❌ قبل: كلاس واحد مسؤول عن كل شيء
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  save() { /* حفظ في قاعدة البيانات */ }
  sendEmail(message) { /* إرسال بريد */ }
  validate() { /* تحقق من البيانات */ }
}

// ✅ بعد: فصل المسؤوليات
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
}

class UserRepository {
  save(user) { /* حفظ في قاعدة البيانات */ }
}

class EmailService {
  sendEmail(user, message) { /* إرسال بريد */ }
}

class UserValidator {
  validate(user) { /* تحقق من البيانات */ }
}

⚠️ إذا وجدت كلمة "و" في وصف الكلاس — فهذا مؤشر على انتهاك SRP.

O — Open/Closed Principle (OCP)

الكائنات مفتوحة للتمديد، مغلقة للتعديل.

// ❌ قبل: تعديل الكود كل مرة نضيف نوعًا جديدًا
class DiscountCalculator {
  calculate(price, type) {
    if (type === "student") return price * 0.9;
    if (type === "vip") return price * 0.8;
    // إضافة نوع جديد = تعديل الدالة
  }
}

// ✅ بعد: مفتوح للتمديد
class Discount {
  apply(price) { return price; }
}

class StudentDiscount extends Discount {
  apply(price) { return price * 0.9; }
}

class VIPDiscount extends Discount {
  apply(price) { return price * 0.8; }
}

class DiscountCalculator {
  calculate(price, discount) {
    return discount.apply(price);
  }
}

L — Liskov Substitution Principle (LSP)

الفئات الفرعية يجب أن تكون قابلة للاستبدال بالفئات الأب دون تغيير سلوك البرنامج.

# ❌ قبل: Rectangle -> Square ينتهك LSP
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def set_width(self, width):
        self.width = width

    def set_height(self, height):
        self.height = height

    def area(self):
        return self.width * self.height

class Square(Rectangle):
    def set_width(self, width):
        self.width = width
        self.height = width  # يغير السلوك!

    def set_height(self, height):
        self.height = height
        self.width = height  # يغير السلوك!

# ✅ بعد: فصل — ليس كل مربع هو مستطيل
class Shape:
    def area(self): ...

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

class Square(Shape):
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side * self.side

I — Interface Segregation Principle (ISP)

لا تجبر الكلاسات على تنفيذ واجهات لا تحتاجها.

// ❌ قبل: واجهة كبيرة
class Worker {
  work() {}
  eat() {}
  sleep() {}
}

class Robot extends Worker {
  work() { /* يعمل */ }
  eat() { throw new Error("الروبوت لا يأكل"); }
  sleep() { throw new Error("الروبوت لا ينام"); }
}

// ✅ بعد: واجهات صغيرة
class Workable {
  work() {}
}

class Eatable {
  eat() {}
}

class Sleepable {
  sleep() {}
}

class Human extends Workable {
  work() { /* يعمل */ }
}

class Robot extends Workable {
  work() { /* يعمل */ }
}

D — Dependency Inversion Principle (DIP)

اعتمد على التجريد (Interfaces/Abstract Classes)، ليس على التنفيذ (Concrete Classes).

// ❌ قبل: الكلاس العالي يعتمد على كلاس منخفض
class MySQLDatabase {
  save(data) { /* حفظ في MySQL */ }
}

class UserService {
  constructor() {
    this.db = new MySQLDatabase(); // تبعية مباشرة
  }
}

// ✅ بعد: الاعتماد على التجريد
class Database {
  save(data) { throw new Error("للتطبيق"); }
}

class MySQLDatabase extends Database {
  save(data) { /* حفظ في MySQL */ }
}

class MongoDBDatabase extends Database {
  save(data) { /* حفظ في MongoDB */ }
}

class UserService {
  constructor(database) {
    this.db = database; // حقن التبعية
  }

  saveUser(user) {
    this.db.save(user);
  }
}

const service = new UserService(new MySQLDatabase());
// أو
const service2 = new UserService(new MongoDBDatabase());

جدول ملخص SOLID

المبدأالمعنىالسؤال المفتاحي
SRPكلاس واحد — مسؤولية واحدةمن سيؤثر عليه التغيير؟
OCPمفتوح للتمديد، مغلق للتعديلهل أحتاج لتعديل الكود الموجود؟
LSPالفئة الفرعية قابلة للاستبدالهل السلوك يبقى صحيحًا؟
ISPواجهات صغيرة مخصصةهل الكلاس يستخدم كل الدوال؟
DIPاعتماد على التجريدهل أعتمد على التفاصيل أم المفاهيم؟

تطبيق SOLID في مشروع حقيقي

# SRP + OCP + DIP — مثال متكامل
from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    @abstractmethod
    def pay(self, amount): ...

class CreditCard(PaymentMethod):
    def pay(self, amount):
        print(f"دفع {amount} عبر بطاقة ائتمان")

class PayPal(PaymentMethod):
    def pay(self, amount):
        print(f"دفع {amount} عبر PayPal")

class PaymentService:
    def __init__(self, payment_method: PaymentMethod):
        self.payment_method = payment_method

    def checkout(self, amount):
        self.payment_method.pay(amount)

# استخدام
service = PaymentService(CreditCard())
service.checkout(100)

الخلاصة

  • SOLID يوجّهك لكتابة كود نظيف، مرن، قابل للتوسّع.
  • كل مبدأ يحل مشكلة محددة — طبقها معًا للحصول على أفضل نتيجة.
  • ليست قوانين صارمة — بل إرشادات تساعدك على اتخاذ قرارات أفضل.

🎯 تهانينا! لقد أكملت مسار OOP → Design Patterns. عد إلى المسارات للمزيد.

شرح مبادئ SOLID — تطبيق عملي — أنماط التصميم (Design Patterns) بالعربي
مبادئ SOLID — تطبيق عمليأنماط التصميم (Design Patterns) بالعربي · The Code Fix

📚 لمزيد من التعمّق في أنماط التصميم (Design Patterns)، راجِع البرمجة الكائنية على ويكيبيديا.

هل كان هذا الدرس مفيدًا؟