Event Bus ونمط Observer في Kotlin: بنية التطبيقات الموجهة بالأحداث
التطوير الحديث في Kotlin، خاصة في سياق تطبيقات Android والتطبيقات الخادمة، يتطلب آليات مرنة للتفاعل بين المكونات. يوفر نمط Observer وتنفيذه العملي - Event Bus - حلاً أنيقًا للبنية ضعيفة الاقتران، حيث يقوم كائن واحد (الناشر) بإخطار العديد من المشتركين بحدوث حدث دون معرفة تنفيذهم المحدد. في هذه المقالة، سنشرح كيفية بناء Event Bus خاص بك في Kotlin باستخدام coroutines والكتابة الآمنة.
نمط Observer: الأساس النظري
يحدد نمط Observer (المراقب) علاقة "واحد إلى متعدد" بين الكائنات. عندما تتغير حالة الموضوع (الناشر)، يتم إخطار جميع الكائنات التابعة (المراقبين) وتحديثها تلقائيًا. في Kotlin، يمكن تنفيذ هذا النمط من خلال الواجهات، أو lambdas، أو بنى أكثر تقدمًا.
العناصر الرئيسية للنمط:
- Subject (الموضوع) — الكائن الذي يدير قائمة المراقبين ويرسل الإخطارات.
- Observer (المراقب) — الكائن الذي يتلقى الإخطارات من الموضوع.
- ConcreteSubject — تنفيذ محدد للموضوع مع حالته الخاصة.
- ConcreteObserver — تنفيذ محدد للمراقب، يتفاعل مع التغييرات.
مثال على أبسط تنفيذ في Kotlin:
interface Observer { fun update(event: String)}
class ConcreteSubject { private val observers = mutableListOf<Observer>()
fun attach(observer: Observer) { observers.add(observer) }
fun detach(observer: Observer) { observers.remove(observer) }
fun notifyObservers(event: String) { observers.forEach { it.update(event) } }}
class ConcreteObserver(private val name: String) : Observer { override fun update(event: String) { println("$name تلقى الحدث: $event") }}
fun main() { val subject = ConcreteSubject() val observer1 = ConcreteObserver("المراقب 1") val observer2 = ConcreteObserver("المراقب 2")
subject.attach(observer1) subject.attach(observer2) subject.notifyObservers("تم تحديث البيانات")}Event Bus: ناقل الأحداث العملي
Event Bus هو آلية مركزية توسع نمط Observer. بدلاً من أن يدير كل موضوع مراقبيه الخاصين، يتم إنشاء ناقل واحد تمر من خلاله جميع الأحداث. هذا يبسط التواصل بين المكونات، خاصة في التطبيقات المعقدة.
مزايا Event Bus:
- اقتران ضعيف: الناشرون والمشتركون لا يعرفون بعضهم البعض.
- سهولة إضافة مشتركين جدد دون تغيير الكود الموجود.
- إمكانية تصفية الأحداث حسب النوع أو العلامة.
- دعم المعالجة غير المتزامنة عبر coroutines.
تنفيذ Event Bus في Kotlin مع coroutines
يجب أن يأخذ التنفيذ الحديث لـ Event Bus في الاعتبار تعدد الخيوط وتجنب تسرب الذاكرة. استخدام Coroutines و Channel يسمح بإنشاء ناقل آمن للخيوط وفعال.
التنفيذ الأساسي لـ Event Bus:
import kotlinx.coroutines.*import kotlinx.coroutines.channels.Channelimport kotlinx.coroutines.flow.*
sealed class Event { data class UserLoggedIn(val userId: String) : Event() data class DataUpdated(val data: String) : Event() object NetworkError : Event()}
class EventBus { private val _events = MutableSharedFlow<Event>(extraBufferCapacity = 64) val events: SharedFlow<Event> = _events.asSharedFlow()
suspend fun publish(event: Event) { _events.emit(event) }
fun subscribe(scope: CoroutineScope, action: (Even