مقدمة في أنماط التصميم بلغة C++
أنماط التصميم (design patterns) هي حلول معمارية مجربة عبر الزمن للمشكلات النمطية في التطوير. في عالم C++، هي مهمة بشكل خاص لأنها تسمح بإنشاء كود مرن وقابل للتوسع والصيانة. في هذه المقالة، سنشرح أربعة أنماط أساسية: Singleton، Factory Method، Observer و Strategy — مع أمثلة كاملة بلغة C++ الحديثة (C++17/20).
سيصاحب كل نمط مثال عملي، ومخطط فئات، وشروحات حول الاستخدام. المادة موجهة للمطورين الذين لديهم معرفة مسبقة بأساسيات C++ والبرمجة كائنية التوجه (OOP).
1. النمط الإنشائي Singleton (المفرد)
يضمن Singleton أن يكون للفصل مثيل واحد فقط، ويوفر نقطة وصول عامة إليه. في C++، يستخدم التنفيذ التقليدي طريقة ثابتة ومنشئًا خاصًا.
متى يتم استخدامه
- إدارة الاتصال بقاعدة البيانات
- نظام تسجيل (logging)
- مدير التخزين المؤقت (Cache Manager)
- إعدادات التطبيق
مثال على التنفيذ (Singleton آمن للخيوط)
#include <iostream>#include <mutex>#include <memory>
class Logger {private: static std::unique_ptr<Logger> instance; static std::mutex mtx; Logger() { std::cout << "Logger تم إنشاؤه" << std::endl; } public: Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; static Logger* getInstance() { std::lock_guard<std::mutex> lock(mtx); if (!instance) { instance.reset(new Logger()); } return instance.get(); } void log(const std::string& msg) { std::cout << "[LOG] " << msg << std::endl; }};
std::unique_ptr<Logger> Logger::instance = nullptr;std::mutex Logger::mtx;
int main() { Logger* log1 = Logger::getInstance(); Logger* log2 = Logger::getInstance(); log1->log("رسالة اختبار"); // log1 و log2 يشيران إلى نفس الكائن std::cout << "log1 == log2: " << (log1 == log2) << std::endl; return 0;}نهج C++ الحديث (Meyers' Singleton)
class ConfigManager {public: static ConfigManager& getInstance() { static ConfigManager instance; // آمن للخيوط في C++11+ return instance; } void setParam(const std::string& key, const std::string& value) { params[key] = value; } std::string getParam(const std::string& key) { return params[key]; } private: ConfigManager() = default; std::map<std::string, std::string> params;};2. النمط الإنشائي Factory Method (طريقة المصنع)
يحدد Factory Method واجهة لإنشاء كائن، لكنه يسمح للفئات الفرعية باختيار الفئة المحددة للكائن المراد إنشاؤه. هذا النمط مفيد بشكل خاص عندما يكون نوع الكائن غير معروف مسبقًا.
هيكل النمط
- Product — فئة المنتج المجردة
- ConcreteProduct — تنفيذ محدد للمنتج
- Creator — فئة المنشئ المجردة مع طريقة المصنع
- ConcreteCreator — يعيد تعريف طريقة المصنع
مثال: نظام الإشعارات
#include <iostream>#include <memory>#include <string>
// منتج مجردclass Notification {public: virtual void send(const std::string& message) = 0; virtual ~Notification() = default;};
// منتجات محددةclass EmailNotification : public Notification {public: void send(const std::str
```