| وجه المقارنة المعمارية | التواصل الهرمي (Input / Output) | التواصل عبر الخدمة المشتركة (Shared Service) |
|---|---|---|
| نطاق الربط بين المكونات | مقتصر حصرياً على المكونات المتصلة ببعضها مباشرة (أب وابن أو أخوة مباشرين) | مرن وشامل، يسمح بربط مكونات شقيقة أو متباعدة تماماً في شجرة العناصر |
| تعقيد تمرير البيانات (Prop Drilling) | يزداد تعقيداً بشكل كبير عند الاضطرار لتمرير البيانات عبر عدة طبقات وسيطة | منعدم تماماً، حيث يتم حقن الخدمة مباشرة في المكون المحتاج للبيانات |
| عزل منطق واجهة المستخدم | قد تضطر لتضخيم كود المكونات الوسيطة بأحداث لا تخصها | فصل تام، حيث يُعزل منطق تداول البيانات داخل الخدمة بعيداً عن ملفات العرض |
عندما تتطلب معمارية التطبيق في Angular 22.1 تبادل البيانات والأحداث بين مكونات متباعدة وغير مرتبطة بعلاقة أب-ابن، تصبح الحلول الهرمية التقليدية عاجزة عن تلبية الاحتياجات. هنا تبرز الخدمات المشتركة (Shared Services) كنمط معماري أساسي يلعب دور الوسيط المركزي؛ حيث تستقبل البيانات أو الأحداث من مكون ما وتعيد توزيعها فورياً على جميع المكونات المستمعة في النظام.
تعتمد الفكرة على إنشاء خدمة يتم توفيرها على مستوى الجذر (providedIn: 'root') لضمان وجود نسخة واحدة متزامنة. تتولى هذه الخدمة إدارة الحالة أو الأحداث وتوفير دوال لتحديثها وقراءتها.
باستخدام الإشارات داخل الخدمة المشتركة، يتم إشعار جميع المكونات المستهلكة للبيانات بأي تغيير فوراَ ودون الحاجة لاشتراكات يدوية معقدة (RxJS subscriptions)، مما يرفع من كفاءة الأداء ويقلل تسريب الذاكرة.
| 1 | import { Injectable, signal } from '@angular/core'; |
| 2 | |
| 3 | export interface SystemMessage { |
| 4 | id: number; |
| 5 | text: string; |
| 6 | category: 'info' | 'success' | 'warning'; |
| 7 | } |
| 8 | |
| 9 | @Injectable({ |
| 10 | providedIn: 'root' |
| 11 | }) |
| 12 | export class EventBusService { |
| 13 | private messagesSignal = signal<SystemMessage[]>([]); |
| 14 | |
| 15 | readonly messages = this.messagesSignal.asReadonly(); |
| 16 | |
| 17 | broadcastMessage(text: string, category: 'info' | 'success' | 'warning' = 'info') { |
| 18 | const newMessage: SystemMessage = { |
| 19 | id: Date.now(), |
| 20 | text, |
| 21 | category |
| 22 | }; |
| 23 | this.messagesSignal.update(list => [newMessage, ...list]); |
| 24 | } |
| 25 | |
| 26 | clearAllMessages() { |
| 27 | this.messagesSignal.set([]); |
| 28 | } |
| 29 | } |
| 1 | <!-- shared-service-demo.component.html --> |
| 2 | <div class="bridge-container"> |
| 3 | <h3>مشاركة البيانات والأحداث عبر الخدمات المشتركة</h3> |
| 4 | |
| 5 | <div class="controls-panel"> |
| 6 | <button (click)="sendInfo()" class="btn-info">إرسال معلومة عامة</button> |
| 7 | <button (click)="sendSuccess()" class="btn-success">إرسال إشعار نجاح</button> |
| 8 | <button (click)="eventBus.clearAllMessages()" class="btn-clear">مسح السجل</button> |
| 9 | </div> |
| 10 | |
| 11 | <div class="messages-stream"> |
| 12 | <h4>الرسائل الواردة عبر الوسيط المركزي:</h4> |
| 13 | @for (msg of eventBus.messages(); track msg.id) { |
| 14 | <div class="message-card" [ngClass]="msg.category"> |
| 15 | <span>{{ msg.text }}</span> |
| 16 | <small>معرف الحدث: {{ msg.id }}</small> |
| 17 | </div> |
| 18 | } @empty { |
| 19 | <p class="empty-state">لا توجد رسائل متبادلة حالياً في النظام.</p> |
| 20 | } |
| 21 | </div> |
| 22 | </div> |