أنماط التصميم في C++: متى ولماذا

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

أنماط التصميم في C++: متى ولماذا

\n\n

هل سبق لك أن أعدت كتابة الكود للمرة العاشرة لأن وظيفة جديدة كسرت البنية القديمة؟ أو أمضيت ساعات في التصحيح محاولاً فهم من ولماذا غيّر متغيرًا عامًا؟ مألوف؟ إذن مرحبًا بك في عالم أنماط التصميم.

\n\n

الأنماط ليست حبة سحرية. إنها حلول مجربة لمشاكل نموذجية. لن تجعل الكود الخاص بك مثاليًا، لكنها ستساعدك على التحدث بلغة واحدة مع المطورين الآخرين وتجنب الأخطاء التي وقع فيها آلاف المبرمجين قبلك.

\n\n

في هذه المقالة، سنحلل ثلاث مجموعات رئيسية من الأنماط في C++: الإنشائية والهيكلية والسلوكية. سنعرف متى يجب استخدامها ومتى يكون من الأفضل تجنبها. هيا بنا!

\n\n

الأنماط الإنشائية: التحكم في إنشاء الكائنات

\n\n

الأنماط الإنشائية مسؤولة عن إنشاء الكائنات بمرونة. فهي تخفي منطق التثبيت وتجعل النظام مستقلاً عن كيفية إنشاء مكوناته.

\n\n

Singleton (المفرد)

\n\n

كلاسيكي. يضمن وجود مثيل واحد فقط للفئة، ويوفر نقطة وصول عالمية إليه. يبدو مغريًا، لكن استخدمه بحكمة - غالبًا ما يصبح Singleton نمطًا معاديًا إذا تضخم إلى حجم "كائن الإله".

\n\n

متى تستخدم: مسجل (logger)، مدير التكوين، تجمع الخيوط (thread pool)، العمل مع الأجهزة.

\n\n

مثال في C++ (آمن للخيوط، C++11 وما بعده):

\n\n
class Logger {\npublic:\n    static Logger& getInstance() {\n        static Logger instance; // يتم التهيئة مرة واحدة، حتى في تعدد الخيوط\n        return instance;\n    }\n\n    void log(const std::string& msg) {\n        std::cout << "[LOG]: " << msg << std::endl;\n    }\n\n    // منع النسخ والتعيين\n    Logger(const Logger&) = delete;\n    Logger& operator=(const Logger&) = delete;\n\nprivate:\n    Logger() = default; // مُنشئ خاص\n    ~Logger() = default;\n};\n\n// الاستخدام\nLogger::getInstance().log("تم تشغيل النظام");
\n\n

Factory Method (طريقة المصنع)

\n\n

يحدد واجهة لإنشاء كائن، لكنه يسمح للفئات الفرعية بتغيير نوع الكائن الذي يتم إنشاؤه. مناسب تمامًا عندما لا تعرف مسبقًا أي فئة ستحتاجها.

\n\n

متى تستخدم: تحليل تنسيقات مختلفة (JSON، XML، YAML)، إنشاء عناصر واجهة مستخدم لأنظمة تشغيل مختلفة، العمل مع قواعد بيانات مختلفة.

\n\n

مثال:

\n\n
// منتج مجرد\nclass Document {\npublic:\n    virtual void open() = 0;\n    virtual ~Document() = default;\n};\n\n// منتجات محددة\nclass PDFDocument : public Document {\n    void open() override { std::cout << "فتح PDF" << std::endl; }\n};\n\nclass WordDocument : public Document {\n    void open() override { std::cout << "فتح Word" << std::endl; }\n};\n\n// المصنع\nclass Application {\npublic:\n    virtual Document* createDocument() = 0; // طريقة المصنع\n    virtual ~Application() = default;\n\n    void newDocument() {\n        Document* doc = createDocument();\n        doc->open();\n        delete doc; // في الكود الحقيقي - مؤشرات ذكية\n    }\n};\n\nclass PDFApp : public Application {\n    Document* createDocument() override { return new PDFDocument(); }\n};\n\n// الاستخدام\nPDFApp app;\napp.newDocument(); // فتح PDF
\n\n

الأنماط الهيكلية: تجميع المكونات

\n\n

تساعد هذه الأنماط في تنظيم الفئات والكائنات في هياكل أكبر، مع الحفاظ على المرونة والكفاءة.

\n\n

Adapter (المهايئ)

\n\n

يسمح للكائنات ذات الواجهات غير المتوافقة بالعمل معًا. تخيل أن لديك مكتبة قديمة للعمل مع XML، ووحدة جديدة تنتظر JSON. المهايئ هو منقذك.

\n\n

متى تستخدم:

المدونات

توصيات الكتب