نظام الأحداث
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 61 من 61.
التحدي
سهللنبنِ نظام إشعارات: بنية تعتمد على event، حيث يمكن لـ handlers متعددة الاشتراك في event والاستجابة عند fire الخاص به. يُعد هذا النمط أساس البرمجة التفاعلية وأطر عمل واجهات المستخدم الرسومية.
ستنظّم شفرتك عبر ثلاثة ملفات:
event.h: عرّف نوع مؤشر الدالةHandlerالذي يأخذ رسالة من النوعconst char*. أنشئ بنيةEventتحتوي على array تضم ما يصل إلى 5 من handlers، بالإضافة إلى عدد handlers المسجّلة. صرّح بالدوال اللازمة لتهيئة event، والاشتراك باستخدام handler، وfire الخاص بـ event لإخطار جميع المشتركين.event.c: نفّذ نظام event:init_event: تأخذ مؤشراً إلى Event وتضبط عدد handlers على 0subscribe: تأخذ مؤشراً إلى Event وHandler، وتضيف handler إلى array إذا كانت هناك مساحة (أي إن كان count أقل من 5)، ثم تزيد countfire: تأخذ مؤشراً إلى Event وmessage string، ثم تستدعي كل handler مسجّلة مع تلك الرسالة بالترتيب الذي اشتركت به
main.c: أنشئ ثلاث دوال handlers مختلفة تستجيب للأحداث بطرق مميزة:logger: تطبع[LOG]متبوعةً بالرسالةalert: تطبع[ALERT]متبوعةً بالرسالةcounter: تستخدم متغيراً static لحساب عدد مرات استدعائها، ثم تطبع[COUNT] Xحيث تمثل X العدد الحالي
سيستقبل برنامجك:
- عدد handlers المطلوب الاشتراك بها (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يوضح هذا تعدد الأشكال من خلال مؤشرات الدوال: إذ يؤدي استدعاء fire نفسه إلى تشغيل سلوكيات مختلفة تماماً اعتماداً على handlers التي تم الاشتراك بها. يستجيب كل handler بطريقته الخاصة إلى event نفسه، مما يبرز الطبيعة غير المقترنة للتصميم القائم على event.
جرّب بنفسك
#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() {
// اقرأ عدد المعالجات للاشتراك
int num_handlers;
scanf("%d", &num_handlers);
getchar(); // استهلك السطر الجديد
// اقرأ الرسالة
char message[256];
fgets(message, sizeof(message), stdin);
message[strcspn(message, "\n")] = '\0'; // إزالة السطر الجديد
// TODO: إنشاء وتهيئة Event
// TODO: الاشتراك في المعالجات بناءً على num_handlers
// 1 معالج: logger
// 2 معالجات: logger, alert
// 3 معالجات: logger, alert, counter
// TODO: إطلاق الحدث مع الرسالة
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكالتدرّب بنفسك: مترجم C عبر الإنترنت