نظام الأحداث
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 61 من 61.
التحدي
سهللنقم ببناء نظام إشعارات (Notification System) — وهو بنية تعتمد على الأحداث (event-driven architecture) حيث يمكن لعدة معالجات (handlers) الاشتراك في حدث ما والاستجابة عند إطلاقه. هذا النمط هو العمود الفقري للبرمجة التفاعلية وأطر عمل واجهات المستخدم الرسومية (GUI).
ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:
event.h: قم بتعريف نوع مؤشر الدالةHandlerالذي يأخذ رسالة من نوعconst char*. أنشئ هيكلEventيحتوي على مصفوفة تصل إلى 5 معالجات وعداد للمعالجات المسجلة. صرّح عن دوال لتهيئة الحدث، والاشتراك بمعالج، وإطلاق الحدث لإخطار جميع المشتركين.event.c: قم بتنفيذ نظام الأحداث الخاص بك:init_event— يأخذ مؤشر Event ويضبط عداد المعالجات على 0subscribe— يأخذ مؤشر Event وHandler، ويضيف المعالج إلى المصفوفة إذا كانت هناك مساحة (العداد أقل من 5)، ويزيد العدادfire— يأخذ مؤشر Event وسلسلة نصية للرسالة، ثم يستدعي كل معالج مسجل مع تلك الرسالة بالترتيب الذي تم الاشتراك به
main.c: أنشئ ثلاث دوال معالجة مختلفة تستجيب للأحداث بطرق فريدة:logger— يطبع[LOG]متبوعاً بالرسالةalert— يطبع[ALERT]متبوعاً بالرسالةcounter— يستخدم متغيراً ساكناً (static variable) لعد المرات التي تم استدعاؤه فيها، ثم يطبع[COUNT] Xحيث X هو العدد الحالي
سيتلقى برنامجك:
- عدد المعالجات للاشتراك (1، 2، أو 3)
- الرسالة المراد بثها
مثال على المخرجات عندما تكون المدخلات 3 و System started:
[LOG] System started
[ALERT] System started
[COUNT] 1مثال على المخرجات عندما تكون المدخلات 2 و Warning detected:
[LOG] Warning detected
[ALERT] Warning detectedمثال على المخرجات عندما تكون المدخلات 1 و Hello:
[LOG] Helloيوضح هذا تعدد الأشكال (polymorphism) من خلال مؤشرات الدوال — حيث يؤدي استدعاء fire نفسه إلى إطلاق سلوكيات مختلفة تماماً اعتماداً على المعالجات المشتركة. يستجيب كل معالج بطريقته الخاصة لنفس الحدث، مما يبرز الطبيعة المنفصلة (decoupled) للتصميم المعتمد على الأحداث.
جرّب بنفسك
#include <stdio.h>
#include <string.h>
#include "event.h"
// TODO: تنفيذ معالج logger
// يطبع "[LOG] " متبوعة بالرسالة
void logger(const char* message) {
// TODO: تنفيذ
}
// TODO: تنفيذ معالج alert
// يطبع "[ALERT] " متبوعة بالرسالة
void alert(const char* message) {
// TODO: تنفيذ
}
// TODO: تنفيذ معالج counter
// يستخدم متغير static لعد الاستدعاءات
// يطبع "[COUNT] X" حيث X هو العدد الحالي
void counter(const char* message) {
// TODO: التنفيذ باستخدام متغير static
}
int main() {
// قراءة عدد الـ handlers للاشتراك
int num_handlers;
scanf("%d", &num_handlers);
getchar(); // استهلاك السطر الجديد
// قراءة الرسالة
char message[256];
fgets(message, sizeof(message), stdin);
message[strcspn(message, "\n")] = '\0'; // إزالة سطر جديد
// TODO: إنشاء وتهيئة Event
// TODO: تسجيل الـ handlers بناءً على num_handlers
// 1 handler: logger
// 2 handlers: logger، alert
// 3 handlers: logger، alert، counter
// TODO: إطلاق الـ event مع الـ message
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكال