نظام الأحداث
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 61 من 61.
التحدي
سهللنقم ببناء Notification System — وهي بنية تعتمد على الأحداث حيث يمكن لعدة معالجات (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) لعد المرات التي تم استدعاؤه فيها، ثم يطبع[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 variable لعد الاستدعاءات
// يطبع "[COUNT] X" حيث X هو العدد الحالي
void counter(const char* message) {
// TODO: التنفيذ باستخدام static variable
}
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
// معالج واحد: logger
// معالجان: logger، alert
// 3 معالجات: logger، alert، counter
// TODO: إطلاق الـ event مع الرسالة
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مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة