December 20, 2025 (3mo ago)

دليل عملي لأنماط التصميم في البرمجة الموجهة للكائنات

اتقن أنماط التصميم في البرمجة الموجهة للكائنات مع دليلنا. تعلّم الأنماط الإنشائية والبنيوية والسلوكية مع أمثلة شفرة عملية وواضحة لرفع مهاراتك.

← Back to blog
Cover Image for دليل عملي لأنماط التصميم في البرمجة الموجهة للكائنات

اتقن أنماط التصميم في البرمجة الموجهة للكائنات مع دليلنا. تعلّم الأنماط الإنشائية والبنيوية والسلوكية مع أمثلة شفرة عملية وواضحة لرفع مهاراتك.

دليل عملي لأنماط التصميم في البرمجة الموجهة للكائنات

اتقن أنماط التصميم في البرمجة الموجهة للكائنات مع دليلنا. تعلّم الأنماط الإنشائية والبنيوية والسلوكية مع أمثلة شفرة عملية وواضحة لرفع مهاراتك.

المقدمة

أنماط التصميم في البرمجة الموجهة للكائنات هي مخططات مثبتة وقابلة لإعادة الاستخدام لحل تحديات تصميم متكررة. ليست شفرات تُنسخ وتُلصق؛ بل قوالب قابلة للتكييف تساعدك على تنظيم الفئات والكائنات بحيث يصبح الكود أسهل في الصيانة والتمديد والاختبار.

فهم قوي للأنماط الشائعة — الإنشائية والبنيوية والسلوكية — يتيح لك توصيل نية التصميم بوضوح مع زملائك، وإعادة هيكلة الكود القديم بأمان، واختيار الأداة المناسبة لكل مشكلة معمارية.

ما هي أنماط التصميم في البرمجة الموجهة للكائنات

هل جرّبت بناء شيء معقد دون خطة؟ الترميز دون أنماط تصميم قد يؤدي إلى قاعدة كود متشابكة يصعب توسيعها وصيانتها. أنماط التصميم تشبه كتاب وصفات الشيف المحترف: وصفات مجرّبة يمكنك تكييفها للحصول على نتائج متسقة وقابلة للصيانة.

مخطط قبعة طاهٍ تسقط أشكال أحرف ذهبية في كتاب طبخ مفتوح.

لغة مشتركة بين المطورين

أحد أكبر فوائد الأنماط هو وجود مفردات مشتركة. قل "Factory" أو "Singleton" وسيفهم المطورون ذوو الخبرة فورًا النية والبنية عالية المستوى، مما يسرّع التعاون وقرارات العمارة.

“Design Patterns: Elements of Reusable Object-Oriented Software,” نُشر عام 1994 بواسطة Erich Gamma وRichard Helm وRalph Johnson وJohn Vlissides، قم بتوثيق 23 نمطًا أساسيًا لا تزال قراءة أساسية لممارسي OOP2. هذه الأنماط تبني على أعمال أكاديمية سابقة أظهرت فوائد قابلة للقياس في الإنتاجية وإعادة الاستخدام في المشاريع الكبيرة1.

النمط التصميمي ليس تصميمًا منتهيًا يمكن تحويله مباشرة إلى كود. إنه وصف أو قالب لكيفية حل مشكلة يمكن استخدامه في مواقف مختلفة.

التأقلم مع مبادئ OOP الأساسية مثل التعدد الشكلي (polymorphism) والوراثة يساعدك على تطبيق الأنماط بفعالية. لمراجعة عملية، انظر دليلنا المقارن بين التعدد الشكلي مقابل الوراثة.

الفئات الثلاث الأساسية لأنماط التصميم

نظّم "عصابة الأربعة" الأنماط في ثلاث فئات: إنشائية وبنيوية وسلوكية. معرفة هذه الفئات يساعدك على اختيار النهج المناسب للمشكلة بسرعة.

مخطط يوضّح الأنماط الإنشائية والبنيوية والسلوكية مع رسومات صندوق بسيطة.

نظرة عامة على فئات أنماط التصميم في OOP

فئة النمطالغرض الأساسيأمثلة شائعة
Creationalإدارة وتجريد إنشاء الكائناتFactory, Builder, Singleton, Prototype
Structuralتجميع الفئات والكائنات في هياكل أكبر ومرنةAdapter, Decorator, Facade, Composite
Behavioralتحديد كيفية تفاعل الكائنات والتواصل بينهاObserver, Strategy, Command, Iterator

الأنماط الإنشائية: اختصاصيو البناء

الأنماط الإنشائية تتحكم بكيفية إنشاء الكائنات حتى لا يرتبط كود العميل ارتباطًا وثيقًا بالفئات الملموسة. تُخفي منطق الإنشاء، تزيد المرونة، وتتيح لك إدارة عملية الاستنساخ (مثل فرض وجود مثيل واحد باستخدام Singleton).

الأنماط البنائية: الصمغ المعماري

الأنماط البنائية تساعدك على تجميع الكائنات في أنظمة أكبر. تُبسط العلاقات بين المكونات بحيث يمكنك تغيير أجزاء دون كسر النظام بأكمله. أنماط مثل Adapter تسمح لواجهات غير متوافقة بالتعاون، وهو أمر ثمين عند دمج مكتبات طرف ثالث.

الأنماط البنائية تُبسط تصميم النظام بتحديد طرق بسيطة لتحقيق العلاقات بين الكيانات.

الأنماط السلوكية: مخرجات التواصل

الأنماط السلوكية تحكم تفاعل الكائنات ومسؤولياتها. تخلق قنوات اتصال نظيفة — Observer للإشعارات المعتمدة على الأحداث وStrategy لتبديل الخوارزميات دون تعديل العملاء.

بإدارة مسارات الاتصال بعناية، تقلل التبعيات وتجعل قاعدة الشفرة أسهل للفهم والصيانة.

إنشاء الكائنات بأنماط إنشائية

الأنماط الإنشائية تُدخل طبقة تجريد حول إنشاء الكائنات، بحيث يمكنك تبديل التنفيذات دون تغيير كود العميل. فيما يلي مثالان عمليان في TypeScript: Singleton وFactory Method.

رسم توضيحي يقارن كائنات فردية تشبه البيض مع خط تجميع يُنتج عناصر ملونة.

نمط Singleton: ضمان وجود مثيل واحد حقيقي

Singleton يضمن أن فئة ما لها مثيل واحد فقط ويوفر نقطة وصول عالمية. مفيد للموارد المشتركة مثل اتصال قاعدة البيانات أو المسجّل (logger)، لكنه قد يُدخل حالة عالمية تعقّد الاختبار وإدارة التبعيات3.

مثال: Singleton في TypeScript لاتصال قاعدة البيانات.

class DatabaseConnection {
  private static instance: DatabaseConnection;

  private constructor() {
    // A private constructor prevents external 'new' calls
    console.log("Connecting to the database...");
  }

  public static getInstance(): DatabaseConnection {
    if (!DatabaseConnection.instance) {
      DatabaseConnection.instance = new DatabaseConnection();
    }
    return DatabaseConnection.instance;
  }

  public query(sql: string): void {
    console.log(`Executing query: ${sql}`);
  }
}

// Usage
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();

db1.query("SELECT * FROM users");
console.log(db1 === db2); // true

المقايضة في Singleton: استخدم Singletons للموارد العالمية حقًا، وفضّل حقن التبعيات (dependency injection) لاختبار أفضل وتقسيم وحدات أكثر3.

طريقة المصنع (Factory Method): ترك القرار للفئات الفرعية حول ما الذي تُنشئه

Factory Method يحدد واجهة لإنشاء كائن، بينما تقرر الفئات الفرعية أي منتج ملموس تُنشئ. يفك ارتباط كود العميل عن الفئات الملموسة، مما يجعل النظام أسهل في التوسيع.

مثال: عرض أزرار خاصة بنظام التشغيل في TypeScript.

interface Button {
  render(): void;
  onClick(f: () => void): void;
}

class WindowsButton implements Button {
  render() { console.log("Rendering a button in Windows style."); }
  onClick(f: () => void) { console.log("Windows button click event."); f(); }
}

class MacButton implements Button {
  render() { console.log("Rendering a button in macOS style."); }
  onClick(f: () => void) { console.log("Mac button click event."); f(); }
}

abstract class Dialog {
  abstract createButton(): Button;

  render() {
    const okButton = this.createButton();
    okButton.render();
  }
}

class WindowsDialog extends Dialog {
  createButton(): Button { return new WindowsButton(); }
}

class MacDialog extends Dialog {
  createButton(): Button { return new MacButton(); }
}

// Client
const os: string = "windows";
let dialog: Dialog;
if (os === "windows") dialog = new WindowsDialog(); else dialog = new MacDialog();
dialog.render();

Factory Method يُبقي المُنشئ غير مدرك للمنتجات الملموسة، مما يجعل إضافة فئات مثل LinuxDialog أمرًا مباشرًا.

بناء أنظمة مرنة بأنماط بنيوية

الأنماط البنيوية تساعدك على تجميع الكائنات في أنظمة قوية وقابلة للتكييف. خياران عمليان هما Adapter وDecorator.

رسومات مرسومة باليد لمحول كهربائي وركم حلقات تمثل أنماط تصميم OOP.

نمط Adapter: جسر بين واجهات غير متوافقة

Adapter يلف واجهة غير متوافقة لتتوافق مع ما يتوقعه نظامك. هذا يتجنب تغييرات تدخّلية على الكود القديم.

مثال: تكييف ModernLogger مع واجهة ILogger الحالية.

class ModernLogger {
  public logInfo(message: string): void {
    console.log(`[INFO]: ${message}`);
  }
}

interface ILogger { log(message: string): void; }

class LoggerAdapter implements ILogger {
  private modernLogger: ModernLogger;
  constructor() { this.modernLogger = new ModernLogger(); }
  public log(message: string): void { this.modernLogger.logInfo(message); }
}

const logger: ILogger = new LoggerAdapter();
logger.log("User logged in successfully.");

نمط Decorator: إضافة وظائف ديناميكيًا

Decorator يضيف مسؤوليات إلى الكائنات في وقت التشغيل عن طريق تغليفها. إنه أكثر مرونة من إنشاء فئات فرعية ويتبع مبدأ المسؤولية الوحيدة.

مثال: تركيب اشتراك مع إضافات اختيارية.

interface Subscription { getDescription(): string; getCost(): number; }

class BasicSubscription implements Subscription {
  getDescription(): string { return "Basic Plan"; }
  getCost(): number { return 10; }
}

abstract class SubscriptionDecorator implements Subscription {
  protected subscription: Subscription;
  constructor(subscription: Subscription) { this.subscription = subscription; }
  abstract getDescription(): string;
  abstract getCost(): number;
}

class PremiumSupportDecorator extends SubscriptionDecorator {
  getDescription(): string { return `${this.subscription.getDescription()}, Premium Support`; }
  getCost(): number { return this.subscription.getCost() + 5; }
}

class CloudStorageDecorator extends SubscriptionDecorator {
  getDescription(): string { return `${this.subscription.getDescription()}, 1TB Cloud Storage`; }
  getCost(): number { return this.subscription.getCost() + 7; }
}

let mySubscription: Subscription = new BasicSubscription();
mySubscription = new PremiumSupportDecorator(mySubscription);
mySubscription = new CloudStorageDecorator(mySubscription);
console.log(mySubscription.getDescription());
console.log(mySubscription.getCost());

هذا النهج التركيبي يحافظ على ميزات قابلة للفصل وسهلة الاختبار.

إدارة التفاعلات بأنماط سلوكية

الأنماط السلوكية تنظّم تواصل الكائنات بحيث تظل الأنظمة مرنة وقابلة للصيانة. مثالان أساسيان هما Observer وStrategy.

نمط Observer: إبلاغ الأطراف المهتمة

Observer ينشئ علاقة واحد-إلى-عديد بحيث عندما يتغير موضوع (Subject) الحالة، يتم إخطار المراقبين تلقائيًا. إنه مثالي للأنظمة المعتمدة على الأحداث.

مثال: خدمة إشعارات بسيطة.

interface Subject { attach(observer: Observer): void; detach(observer: Observer): void; notify(): void; }
interface Observer { update(subject: Subject): void; }

class NotificationService implements Subject {
  public state: string = '';
  private observers: Observer[] = [];
  attach(observer: Observer): void { this.observers.push(observer); }
  detach(observer: Observer): void { const i = this.observers.indexOf(observer); if (i !== -1) this.observers.splice(i, 1); }
  notify(): void { for (const o of this.observers) o.update(this); }
  public createNewPost(title: string): void { this.state = `New Post: ${title}`; console.log(`\nNotificationService: A new post was created.`); this.notify(); }
}

class EmailNotifier implements Observer { public update(subject: Subject): void { if (subject instanceof NotificationService) console.log(`EmailNotifier: Sending email about "${subject.state}"`); } }
class PushNotifier implements Observer { public update(subject: Subject): void { if (subject instanceof NotificationService) console.log(`PushNotifier: Sending push notification for "${subject.state}"`); } }

const notificationService = new NotificationService();
const emailer = new EmailNotifier();
const pusher = new PushNotifier();
notificationService.attach(emailer);
notificationService.attach(pusher);
notificationService.createNewPost("Understanding Observer Pattern");
notificationService.detach(pusher);
notificationService.createNewPost("Why Strategy is Awesome");

Observer ينتج تصميمًا منخفض الربط: الموضوعات لا تحتاج لمعرفة المراقبين الملموسين الذين تُبلغهم.

نمط Strategy: تغليف الخوارزميات

Strategy يتيح لك تبديل الخوارزميات في وقت التشغيل، متجنبًا كتل الشروط الكبيرة. يتماشى مع مبدأ Open/Closed بالسماح باستراتيجيات جديدة دون تعديل الكود القائم4.

مثال: استراتيجيات الدفع لعربة التسوق.

interface PaymentStrategy { pay(amount: number): void; }
class CreditCardStrategy implements PaymentStrategy { pay(amount: number): void { console.log(`Paying $${amount} with Credit Card.`); } }
class PayPalStrategy implements PaymentStrategy { pay(amount: number): void { console.log(`Paying $${amount} via PayPal.`); } }

class ShoppingCart {
  private paymentStrategy: PaymentStrategy;
  constructor(strategy: PaymentStrategy) { this.paymentStrategy = strategy; }
  public setPaymentStrategy(strategy: PaymentStrategy) { this.paymentStrategy = strategy; }
  public checkout(amount: number): void { this.paymentStrategy.pay(amount); }
}

const cart = new ShoppingCart(new CreditCardStrategy());
cart.checkout(150);
cart.setPaymentStrategy(new PayPalStrategy());
cart.checkout(150);

Strategy يزيل تعقيد الشروط ويجعل الأنظمة أسهل في التوسيع.

مطبات تصميم شائعة واستراتيجيات إعادة الهيكلة

اختيار نمط هو نصف المعركة فقط. تجنّب الأنماط المضادة مثل God Object، الذي يحتكر المسؤوليات وينتهك مبدأ المسؤولية الوحيدة. ابحث عن روائح الكود — طرق طويلة، تبعيات مفرطة، أو فئات عملاقة — وعالجها بإعادة هيكلة منهجية.

إعادة الهيكلة تتعلق بتحسين البنية الداخلية دون تغيير السلوك الخارجي. إنها الطريقة التي تُروّض بها الأنظمة القديمة بأمان.

إعادة الهيكلة إلى نمط Strategy

سلسلة switch كبيرة أو if/else طويلة هي رائحة كود كلاسيكية. أعد الهيكلة عن طريق استخراج السلوك المتغير إلى واجهة Strategy مع فئات استراتيجية ملموسة. استبدل الشرط باستدعاء واحد لطريقة الاستراتيجية المحددة. هذا التغيير يحسن القابلية للتوسيع والاختبار والتوافق مع مبادئ SOLID4.

الإجابة على أسئلتكم حول أنماط تصميم OOP

كم عدد أنماط التصميم التي يجب أن أتعلمها؟

ركّز أولًا على 5–7 أنماط أساسية: Singleton, Factory, Adapter, Decorator, Observer, وStrategy. تعلّم المشكلة التي يحلها كل نمط؛ بمجرد استيعاب ذلك، يصبح تعلم الأنماط الإضافية أسهل بكثير.

متى يجب أن أتجنب استخدام نمط تصميم؟

تجنّب الأنماط التي تضيف تعقيدًا دون حل مشكلة حقيقية. لا تُدخل نمطًا "فقط في حال". اتبع مبدأ YAGNI: أضف الأنماط عندما تبررها مشكلة واضحة وحاضرة.

هل يمكنني استخدام أنماط التصميم مع البرمجة الوظيفية؟

نعم. العديد من الأنماط تتطابق طبيعيًا مع تقنيات وظيفية. يمكن أن تكون Strategy معاملات دالة، وDecorator يمكن أن يكون دوال عالية الرتبة. المفتاح هو تطبيق المبدأ الأساسي بدلًا من تقليد أشكال OOP بشكل جامد.


في Clean Code Guy، نساعد الفرق على بناء برمجيات تدوم عن طريق تضمين المبادئ الأساسية في سير عملهم. اكتشف كيف أن مراجعات الكود لدينا وإعادة الهيكلة الجاهزة للذكاء الاصطناعي يمكن أن تجعل فريقك يُصدر بثقة على https://cleancodeguy.com.

1.
W. G. Griswold et al., “A Formal Foundation for Design Pattern Abstraction and Reuse,” Proceedings of ECOOP ’93, University of California, San Diego. https://cseweb.ucsd.edu/~wgg/CSE210/ecoop93-patterns.pdf
2.
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1994). https://en.wikipedia.org/wiki/Design_Patterns
3.
Martin Fowler, “Singleton,” Bliki, discusses Singleton trade-offs and testing implications. https://martinfowler.com/bliki/Singleton.html
4.
Robert C. Martin (Uncle Bob), “The SOLID Principles,” which explain Open/Closed and related design goals. https://8thlight.com/blog/uncle-bob/2012/08/13/the-s-o-l-i-d-principles.html
← Back to blog
🙋🏻‍♂️

الذكاء الاصطناعي يكتب الكود.
أنت تجعله يدوم.

في عصر تسريع الذكاء الاصطناعي، الكود النظيف ليس مجرد ممارسة جيدة — إنه الفرق بين الأنظمة التي تتوسع وقواعد الكود التي تنهار تحت وزنها.