مقدمة في أنماط التصميم
جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 90 من 104.
أنماط التصميم هي حلول مجربة وقابلة لإعادة الاستخدام لمشكلات شائعة تظهر في تصميم البرمجيات. وهي ليست أكواداً تنسخها مباشرة - بل هي قوالب أو مخططات تصف كيفية هيكلة الفئات والكائنات لحل تحديات معينة بأناقة.
تم تعميم هذا المفهوم من قبل "عصابة الأربعة" (GoF) في كتابهم الصادر عام 1994، والذي صنف 23 نمطاً أساسياً. عادة ما يتم تجميع هذه الأنماط في ثلاث فئات:
| الفئة | الغرض | أمثلة |
|---|---|---|
| إنشائية (Creational) | آليات إنشاء الكائنات | Singleton, Factory, Builder |
| هيكلية (Structural) | تكوين الفئات والكائنات | Adapter, Decorator, Composite |
| سلوكية (Behavioral) | تفاعل الكائنات والمسؤولية | Observer, Strategy, Command |
لماذا نتعلم أنماط التصميم؟ فهي توفر لغة مشتركة بين المطورين - فقول "استخدم Factory هنا" يوصل فكرة معقدة على الفور. كما أنها تساعدك على تجنب إعادة اختراع الحلول وتجعل الكود الخاص بك أكثر مرونة وقابلية للصيانة.
في لغة ++C، تستفيد أنماط التصميم من ميزات البرمجة كائنية التوجه (OOP) التي تعلمتها بالفعل: الوراثة (inheritance)، وتعدد الأشكال (polymorphism)، والأصناف المجردة (abstract classes)، والقوالب (templates). خلال الدروس القادمة، ستقوم بتنفيذ عدة أنماط أساسية وفهم متى يكون كل منها الأداة المناسبة للمهمة.
التحدي
سهللنقم ببناء مصنف أنماط بسيط يوضح فهمك للفئات الثلاث لأنماط التصميم. ستقوم بإنشاء نظام يأخذ اسم النمط ويحدد الفئة التي ينتمي إليها—Creational، أو Structural، أو Behavioral—بالإضافة إلى وصف موجز لغرض تلك الفئة.
ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:
PatternCategory.h: قم بتعريف فئة أساسية مجردة تسمىPatternCategoryتمثل فئة نمط التصميم. يجب أن تحتوي على:- دالة افتراضية نقية (pure virtual method) باسم
getName()تعيد اسم الفئة كسلسلة نصية (string) - دالة افتراضية نقية باسم
getPurpose()تعيد وصفاً لما تفعله الأنماط في هذه الفئة - مدمر افتراضي (virtual destructor)
ثم قم بإنشاء ثلاث فئات مشتقة ترث من
PatternCategory:CreationalCategory— تعيد الاسم"Creational"والغرض"Object creation mechanisms"StructuralCategory— تعيد الاسم"Structural"والغرض"Class and object composition"BehavioralCategory— تعيد الاسم"Behavioral"والغرض"Object interaction and responsibility"
- دالة افتراضية نقية (pure virtual method) باسم
PatternClassifier.h: قم بإنشاء فئةPatternClassifierيمكنها تحديد الفئة التي ينتمي إليها نمط معين.يجب أن يحتوي المصنف الخاص بك على دالة
classifyتأخذ اسم النمط (string) وتعيد مؤشراً إلىPatternCategoryالمناسب. استخدم المؤشرات الذكية (std::unique_ptr) لإدارة الذاكرة.يجب أن يتعرف المصنف على هذه الأنماط:
- Creational:
Singleton،Factory،Builder - Structural:
Adapter،Decorator،Composite - Behavioral:
Observer،Strategy،Command
إذا لم يتم التعرف على اسم النمط، فقم بإرجاع
nullptr.- Creational:
main.cpp: اقرأ مدخلاً واحداً—اسم نمط التصميم.قم بإنشاء
PatternClassifierواستخدمه لتصنيف النمط المدخل. إذا تم التعرف على النمط، فاطبع:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]إذا لم يتم التعرف على النمط، فاطبع:
Unknown pattern: [PatternName]
على سبيل المثال، مع المدخل Singleton:
Singleton is a Creational pattern
Purpose: Object creation mechanismsمع المدخل Observer:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibilityمع المدخل Proxy:
Unknown pattern: Proxyيعزز هذا التحدي الفئات الثلاث لأنماط التصميم مع التدرب على الوراثة، وتعدد الأشكال (polymorphism)، والمؤشرات الذكية—وهي مفاهيم أتقنتها بالفعل. يعكس الهيكل متعدد الملفات كيفية تنظيم المشاريع الحقيقية للفئات ذات الصلة.
ورقة مرجعية
أنماط التصميم هي حلول قابلة لإعادة الاستخدام لمشاكل تصميم البرمجيات الشائعة. وهي تعمل كقوالب لهيكلة الفئات (classes) والكائنات (objects)، وليست كوداً مباشراً للنسخ.
يتم تجميع أنماط التصميم في ثلاث فئات رئيسية:
| الفئة | الغرض | أمثلة |
|---|---|---|
| الإنشائية (Creational) | آليات إنشاء الكائنات | Singleton, Factory, Builder |
| الهيكلية (Structural) | تكوين الفئات والكائنات | Adapter, Decorator, Composite |
| السلوكية (Behavioral) | تفاعل الكائنات والمسؤولية | Observer, Strategy, Command |
فوائد أنماط التصميم:
- توفير مفردات مشتركة بين المطورين
- تجنب إعادة اختراع الحلول للمشاكل الشائعة
- جعل الكود أكثر مرونة وقابلية للصيانة
في لغة C++، تستفيد أنماط التصميم من ميزات البرمجة كائنية التوجه (OOP) بما في ذلك inheritance، وpolymorphism، وabstract classes، وtemplates.
جرّب بنفسك
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// قراءة اسم النمط
std::string patternName;
std::cin >> patternName;
// TODO: إنشاء مثيل (instance) من PatternClassifier
// TODO: استخدام المصنف (classifier) لتصنيف نمط الإدخال
// TODO: إذا تم التعرف على النمط، اطبع:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO: إذا لم يتم التعرف على النمط (nullptr)، اطبع:
// "Unknown pattern: [PatternName]"
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات الـ OOP
الملفات الخارجيةبناء وتجميع (Compilation) لغة C++ملفات الـ Header وملفات الـ Sourceالـ Namespaces والـ Scopeمقدمة في الـ OOP في C++الـ Classes مقابل الـ Objectsالمؤشر 'this'الـ Methods (الدوال الأعضاء)الـ Attributes (بيانات الأعضاء)أساسيات الـ Ctors والـ Dtorsمراجعة - آلة حاسبة بسيطة4خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticدوال الـ Getters والـ Settersدوال الأعضاء الثابتة (Const)الكلمة المفتاحية Mutableالدوال والمتغيرات الساكنة (Static)الدوال والفئات الصديقة (Friend)مراجعة - مدير الحساب البنكي7الوراثة
الوراثة الأساسيةمستويات الوصول في الوراثةترتيب استدعاء الـ Ctor والـ Dtorإعادة تعريف الدوال (Method Overriding)الدوال الافتراضية والـ VTableالوراثة المتعددةالوراثة الافتراضيةمراجعة - هيكلية الموظفين10نظرة عامة على STL
نظرة عامة وفلسفة STLحاويات STLالـ Iteratorsخوارزميات STLالـ Functors وتعبيرات Lambdaمراجعة - تكرار الكلمات13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factory و Abstract Factoryنمط Builderنمط Observerنمط Strategy2إدارة الذاكرة
ذاكرة Stack مقابل Heapالمؤشرات والمراجعالذاكرة الديناميكية (new/delete)المؤشرات الذكية في C++RAII في C++مراجعة - مدير المصفوفات الديناميكية5التغليف (Encapsulation)
محددات الوصول في C++محددات الوصول بشكل متعمقإخفاء المعلوماتStruct مقابل Classالأصناف المتداخلة والداخليةمراجعة - نظام سجلات الطلاب8تعدد الأشكال (Polymorphism)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالتحميل الزائد للدوال (Function Overloading)مراجعة الدوال الافتراضية (Virtual Functions)الدوال الافتراضية البحتة (Pure Virtual Functions)الأصناف المجردة (Abstract Classes)تصميم الواجهات (Interface) في C++التحويل الديناميكي (Dynamic Casting) و RTTIملخص - حاسبة الأشكال11مفاهيم OOP المتقدمة
التركيب مقابل الوراثةالـ Mixins عبر CRTPنمط Pimplمحو النوع (Type Erasure)أصناف Enum والأنواع القويةمعالجة الاستثناءات في OOPتسلسلات الاستثناءات المخصصة14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط قالب الطريقةنمط الحالةنمط التركيبRAII كنمط3المنشئات والموادم
المنشئ الافتراضيالمنشئ ذو المعاملاتمنشئ النسخمنشئ النقلقوائم تهيئة المنشئالمنشئات المفوضةتعمق في الموادمقاعدة الثلاثة / الخمسة / الصفرمراجعة - فئة String6تحميل العوامل (Operator Overloading)
مقدمة في تحميل العواملتحميل العوامل الحسابيةتحميل عوامل المقارنةعوامل Streamتحميل عامل التعيينتحميل العوامل [] و ()عوامل تحويل النوعمراجعة - Matrix Class9القوالب
قوالب الدوالقوالب الأصنافتخصيص القوالبالقوالب المتغيرةأساسيات SFINAE و Type Traitsمراجعة - الحاويات العامة