Event Bus ونمط Observer في C++: من النظرية إلى التطبيق
\n\nفي تطوير البرمجيات الحديثة بلغة C++، يلعب الترابط الضعيف بين المكونات دورًا مهمًا. يوفر نمط Observer (المراقب) وتطوره - Event Bus (ناقل الأحداث) - آلية أنيقة لتنظيم التفاعل بين الكائنات دون إنشاء تبعيات صلبة. في هذه المقالة، سنشرح بالتفصيل كيفية تنفيذ هذه الأنماط بلغة C++، وسنناقش مزاياها وقيودها، وسنقدم أمثلة عملية على الكود.
\n\nنمط Observer: التنفيذ الكلاسيكي
\n\nيحدد نمط Observer علاقة "واحد إلى متعدد" بين الكائنات: عندما يغير كائن واحد (الموضوع) حالته، يتم إخطار جميع الكائنات التابعة له (المراقبون) تلقائيًا بذلك. في C++، يبدو التنفيذ الكلاسيكي كما يلي:
\n\n#include <iostream>\n#include <vector>\n#include <memory>\n#include <algorithm>\n\n// واجهة المراقب\nclass IObserver {\npublic:\n virtual ~IObserver() = default;\n virtual void update(const std::string& message) = 0;\n};\n\n// مراقب محدد\nclass ConcreteObserver : public IObserver {\nprivate:\n std::string name;\npublic:\n explicit ConcreteObserver(const std::string& n) : name(n) {}\n void update(const std::string& message) override {\n std::cout << "[" << name << "] تم الاستلام: " << message << std::endl;\n }\n};\n\n// الموضوع (الكائن المراقب)\nclass Subject {\nprivate:\n std::vector<std::shared_ptr<IObserver>> observers;\n std::string state;\npublic:\n void attach(std::shared_ptr<IObserver> observer) {\n observers.push_back(observer);\n }\n void detach(std::shared_ptr<IObserver> observer) {\n observers.erase(\n std::remove(observers.begin(), observers.end(), observer),\n observers.end()\n );\n }\n void notify() {\n for (auto& observer : observers) {\n observer->update(state);\n }\n }\n void setState(const std::string& newState) {\n state = newState;\n notify();\n }\n};\n\nint main() {\n Subject subject;\n auto obs1 = std::make_shared<ConcreteObserver>("المراقب 1");\n auto obs2 = std::make_shared<ConcreteObserver>("المراقب 2");\n \n subject.attach(obs1);\n subject.attach(obs2);\n \n subject.setState("حدث #1 وقع!");\n subject.detach(obs1);\n subject.setState("حدث #2 بدون المراقب الأول");\n \n return 0;\n}\n\nEvent Bus: ناقل أحداث مركزي
\n\nيوسع Event Bus فكرة Observer من خلال توفير آلية مركزية لتبادل الرسائل. بدلاً من أن يخزن كل موضوع قائمة بالمراقبين، تمر جميع الاشتراكات والنشرات عبر ناقل واحد. يسمح هذا بما يلي:
\n- \n
- تقليل الترابط - لا يعرف المرسلون والمستقبلون شيئًا عن بعضهم البعض. \n
- تبسيط التوسع - تتم إضافة أنواع جديدة من الأحداث دون تغيير الكود الموجود. \n
- توفير المرونة - يمكن إضافة وإزالة المشتركين في وقت التشغيل. \n
مثال على تنفيذ Event Bus بلغة C++ باستخدام القوالب و std::function:
\n\n#include <iostream>\n#include <unordered_map>\n#include <functional>\n#include <any>\n#include <typeindex>\n#include <vector>\n#include <memory>\n\n// الفئة الأساسية للأحداث\nstruct Event {\n virtual ~Event() = default;\n};\n\n// حدث محدد\nstruct UserLoginEvent : public Event {\n std::string username;\n explicit UserLoginEvent(std::string name) : username(std::move(name)) {}\n};\n\n// فئة Event Bus\nclass EventBus {\nprivate:\n std::unordered_map<std::type_index, std::vector<std::function<void(const std::any&)>>> hand