Observer Pattern
Observer Pattern هو نمط تصميم سلوكي يسمح لكائن واحد، يسمى subject، بإعلام كائنات أخرى، تسمى observers، عندما يتغير شيء ما. يتم استخدامه بشكل شائع لبناء أنظمة تعتمد على event حيث يمكن لإجراء واحد أن يؤدي إلى تفاعلات متعددة دون ربط الكائن الرئيسي بإحكام بجميع الكائنات التي تستجيب له.
يكون هذا النمط مفيدًا في البرمجة كائنية التوجه عندما يحتاج التطبيق إلى إشعارات تلقائية، أو event listeners، أو model observers، أو التسجيل، أو إرسال البريد الإلكتروني، أو تحديثات ذاكرة التخزين المؤقت، أو تحديثات واجهة المستخدم، أو إجراءات الخلفية بعد حدوث event محدد.
مقدمة
في المقالات السابقة من سلسلة Design Patterns، ناقشنا أنماطًا مثل Repository، وStrategy، وFacade، وDecorator، وAdapter، وFactory، وBuilder، وSingleton. يحل كل نمط مشكلة تصميم معينة في البرامج الموجهة للكائنات.
ينتمي Observer Pattern إلى أنماط التصميم السلوكية. تركز الأنماط السلوكية على التواصل بين الكائنات وكيفية توزيع المسؤوليات.
يعد Observer مهمًا بشكل خاص لأن العديد من التطبيقات الحقيقية تعتمد على event. على سبيل المثال، عندما يقوم المستخدم بالتسجيل، قد يحتاج النظام إلى إرسال بريد إلكتروني ترحيبي، وإنشاء ملف تعريف، وتسجيل النشاط، وإرسال إشعار إداري، وبدء سير عمل الإعداد. بدلاً من وضع كل هذه الإجراءات مباشرة داخل رمز التسجيل، يسمح Observer Pattern بمعالجتها بواسطة observers أو listeners منفصلة.
ما هو Observer Pattern؟
يحدد Observer Pattern علاقة رأس بأطراف بين الكائنات. عندما يغير subject حالته أو ينفذ إجراءً مهمًا، يتم إخطار جميع observers المسجلين تلقائيًا.
بعبارات بسيطة، لا يحتاج subject إلى معرفة ما يفعله كل observer بالضبط. إنه يعرف فقط أنه يجب إخطار observers. يقرر كل observer كيفية الرد.
على سبيل المثال، قد يقوم كائن الطلب بإعلام observers عند تقديم الطلب. قد يرسل أحد observer بريدًا إلكترونيًا، وقد يقوم آخر بتحديث المخزون، وقد يقوم آخر بإنشاء فاتورة، وقد يقوم آخر بتسجيل التحليلات.
الفكرة الرئيسية لـ Observer Pattern
الفكرة الرئيسية لـ Observer Pattern هي تقليل tight coupling بين الكائن الذي يقوم بتشغيل event والكائنات التي تستجيب لذلك event.
بدلاً من كتابة جميع الإجراءات داخل class، يعرض subject طرقًا لإرفاق observers وفصله وإخطاره. يقوم Observers بتنفيذ interface المشترك والرد عندما يتم إخطارهم.
وهذا يجعل النظام أسهل في التوسع. يمكن إضافة observers جديد دون تعديل subject class.
لماذا يعد Observer Pattern مهمًا
يعد Observer Pattern مهمًا لأنه يساعد على فصل المسؤوليات. لا ينبغي أن يحتاج class إلى معرفة كل الإجراء المحتمل الذي يجب أن يحدث بعد event.
بدون Observer Pattern، قد تصبح خدمة واحدة مسؤولة عن العديد من المهام. على سبيل المثال، قد تقوم خدمة تسجيل المستخدم بإنشاء المستخدم، وإرسال البريد الإلكتروني، وإنشاء ملف تعريف، وتسجيل النشاط، وإرسال الرسائل القصيرة، وتحديث التحليلات، وإخطار المسؤولين. وهذا يجعل الخدمة كبيرة ويصعب صيانتها.
مع Observer Pattern، يمكن لخدمة التسجيل التركيز على تسجيل المستخدم. يمكن معالجة التفاعلات الأخرى بواسطة observers أو listeners.
مشكلة بدون Observer Pattern
تخيل عملية تسجيل مستخدم بدون Observer Pattern:
class UserRegistrationService
{
public function register(array $data): User
{
$user = User::create($data);
$this->emailService->sendWelcomeEmail($user);
$this->profileService->createProfile($user);
$this->logger->info('User registered', ['id' => $user->id]);
$this->adminNotifier->notifyNewUser($user);
$this->analyticsService->trackRegistration($user);
return $user;
}
}يعمل هذا الرمز، لكن خدمة التسجيل تعرف الآن العديد من الأنظمة المختلفة. إذا كان لا بد من حدوث إجراء جديد بعد التسجيل، فيجب تعديل class مرة أخرى.
يحل Observer Pattern هذه المشكلة عن طريق نقل هذه التفاعلات إلى observer أو listener classes المنفصلة.
هيكل Observer Pattern الأساسي
يتضمن Observer Pattern عادةً هذه الأجزاء الرئيسية:
- Subject: الكائن الذي يقوم بتخزين observers ويبلغه عند حدوث event.
- Observer interface: يحدد الطريقة التي يجب أن يقوم observers بتنفيذها.
- Concrete observers: Classes التي تتفاعل مع إشعارات subject.
- Client code: الكود الذي يربط observers بـ subject ويقوم بتشغيل event.
تسمح هذه البنية لـ subject بإخطار العديد من observers دون الاعتماد على concrete classes.
مثال Observer Pattern الأساسي في PHP
أولاً، قم بتعريف observer interface:
interface Observer
{
public function update(string $event, array $data): void;
}حدد الآن subject class الذي يمكنه إرفاق observers وإخطاره:
class Subject
{
private array $observers = [];
public function attach(Observer $observer): void
{
$this->observers[] = $observer;
}
public function notify(string $event, array $data): void
{
foreach ($this->observers as $observer) {
$observer->update($event, $data);
}
}
}لا يعرف Subject class ما يفعله كل observer. فهو يستدعي فقط طريقة التحديث على كل observer المسجل.
إنشاء Concrete Observers
Concrete observers ينفذ Observer interface ويحدد رد فعله الخاص.
class EmailObserver implements Observer
{
public function update(string $event, array $data): void
{
if ($event === 'user.registered') {
echo 'Sending welcome email to ' . $data['email'];
}
}
}
class LogObserver implements Observer
{
public function update(string $event, array $data): void
{
echo 'Logging event: ' . $event;
}
}
class AnalyticsObserver implements Observer
{
public function update(string $event, array $data): void
{
echo 'Tracking analytics for event: ' . $event;
}
}يتحمل كل observer مسؤولية محددة. يرسل أحدهم البريد الإلكتروني، ويسجل الآخر النشاط، ويتتبع الآخر التحليلات.
باستخدام Observer Pattern
يمكن لـ كود العميل إرفاق observers وتشغيل إشعار:
$subject = new Subject();
$subject->attach(new EmailObserver());
$subject->attach(new LogObserver());
$subject->attach(new AnalyticsObserver());
$subject->notify('user.registered', [
'id' => 1,
'email' => 'user@example.com',
]);عند تشغيل event، يتلقى جميع observers المرفق الإشعار ويقومون بعملهم الخاص.
وهذا يجعل توسيع النظام أسهل لأنه يمكن إضافة observer جديد دون تغيير subject class.
مثال من العالم الحقيقي: تسجيل المستخدم Event
يعد تسجيل المستخدم أحد الأمثلة الأكثر شيوعًا لـ Observer Pattern. عندما يقوم مستخدم جديد بالتسجيل، قد يلزم اتخاذ العديد من الإجراءات المستقلة.
تشمل observers المحتملة ما يلي:
- أرسل مرحباً بالبريد الإلكتروني Observer
- إنشاء ملف تعريف المستخدم Observer
- تسجيل المستخدمObserver
- NotifyAdminObserver
- تتبع تحليلات التسجيل Observer
يمكن إضافة أو إزالة كل observer دون تغيير منطق التسجيل الأساسي.
مثال لتسجيل المستخدم Observer في PHP
interface UserRegisteredObserver
{
public function handle(User $user): void;
}
class SendWelcomeEmailObserver implements UserRegisteredObserver
{
public function handle(User $user): void
{
// Send welcome email
}
}
class CreateProfileObserver implements UserRegisteredObserver
{
public function handle(User $user): void
{
// Create user profile
}
}
class NotifyAdminObserver implements UserRegisteredObserver
{
public function handle(User $user): void
{
// Notify admin about new user
}
}الآن يمكن لعملية التسجيل إخطار جميع observers بعد إنشاء المستخدم.
مثال على تسجيل المستخدم Subject
class UserRegistrationSubject
{
private array $observers = [];
public function attach(UserRegisteredObserver $observer): void
{
$this->observers[] = $observer;
}
public function notify(User $user): void
{
foreach ($this->observers as $observer) {
$observer->handle($user);
}
}
}يعتبر subject مسؤولاً عن إخطار observers، ولكنه لا يحتوي على منطق إرسال رسائل البريد الإلكتروني أو إنشاء ملفات تعريف أو إخطار المسؤولين.
Observer Pattern وEvents
في التطبيقات الحديثة، غالبًا ما يتم تنفيذ Observer Pattern باستخدام events وlisteners. يمثل event شيئًا ما حدث في النظام. listener هو class الذي يتفاعل مع event.
على سبيل المثال، UserRegistered هو event، وSendWelcomeEmail هو listener. هذا هو الاختلاف العملي لـ Observer Pattern.
تستخدم العديد من أطر العمل أنظمة event لأنها توفر طريقة نظيفة لتنظيم ردود الفعل على الإجراءات المهمة.
مثال Event وListener
يمكن لـ event class البسيط تخزين بيانات event:
class UserRegisteredEvent
{
public function __construct(
public User $user
) {
}
}يمكن أن يستجيب listener إلى event:
class SendWelcomeEmailListener
{
public function handle(UserRegisteredEvent $event): void
{
// Send email to $event->user
}
}يحمل كائن event البيانات، ويعالج listener التفاعل.
Observer Pattern في Laravel
يستخدم Laravel أنماط نمط observer بطرق متعددة. لديها مشتركين events وlisteners وmodel observers والإشعارات وqueued listeners وevent.
Laravel events تسمح للمطورين بإرسال event مثل UserRegistered. يمكن أن تستجيب عدة listeners لنفس event. هذا قريب جدًا من Observer Pattern.
على سبيل المثال، بعد قيام المستخدم بالتسجيل، يمكن لـ Laravel إرسال event مسجل بواسطة المستخدم. يمكن لـ Listeners إرسال بريد إلكتروني ترحيبي، أو إنشاء بيانات الملف الشخصي، أو إخطار المسؤولين، أو تشغيل التحليلات.
مثال Laravel Event
قد يبدو Laravel event كما يلي:
class UserRegistered
{
public function __construct(
public User $user
) {
}
}قد يبدو listener كما يلي:
class SendWelcomeEmail
{
public function handle(UserRegistered $event): void
{
// Send welcome email to $event->user
}
}يمكن للتطبيق إرسال event بعد التسجيل:
event(new UserRegistered($user));يسمح هذا لعدة listeners بالتفاعل دون وضع جميع الإجراءات داخل خدمة التسجيل.
Laravel Model Observers
يوفر Laravel أيضًا model observers. model observer هو class الذي يستمع إلى دورة حياة model مثل event مثل الإنشاء والتحديث والحذف والاستعادة والحذف القسري.
على سبيل المثال، يمكن أن يتفاعل UserObserver عند إنشاء مستخدم model:
class UserObserver
{
public function created(User $user): void
{
// React after user is created
}
public function updated(User $user): void
{
// React after user is updated
}
}يكون هذا مفيدًا عندما ترتبط الإجراءات بشكل مباشر بتغييرات model. ومع ذلك، يجب على المطورين تجنب وضع قدر كبير جدًا من سير عمل الأعمال داخل model observers، لأنه قد يجعل تتبع السلوك أكثر صعوبة.
Observer Pattern في Symfony
يحتوي Symfony على مكون إرسال event قوي. فهو يسمح للمطورين بإرسال events وتسجيل listeners أو المشتركين.
هذا هو تطبيق على مستوى إطار العمل لـ Observer Pattern. يعمل المرسل event كـ subject، بينما يعمل listeners والمشتركون كـ observers.
Symfony events مفيدة للمصادقة events ودورة حياة request events والمجال events والإشعارات والتسجيل وسير عمل التطبيقات المخصصة.
Observer Pattern والنشر والاشتراك
يرتبط Observer Pattern بنمط النشر والاشتراك، لكنهما ليسا متماثلين تمامًا.
في classic Observer Pattern، يعرف subject عادةً observers مباشرة. تم تسجيل Observers في subject، ويقوم subject بإعلامهم.
في أنظمة النشر والاشتراك، غالبًا ما يتم الفصل بين الناشرين والمشتركين بواسطة وسيط رسائل أو ناقل event. قد لا يعرف الناشر من يتلقى الرسالة. يؤدي هذا إلى إنشاء فصل أقوى وهو أمر شائع في الأنظمة الموزعة.
في التطبيقات البسيطة، قد يبدو نظاما Observer وevent/listener متشابهين جدًا.
Observer Pattern والمجال Events
المجال events هو events الذي يمثل إجراءات الأعمال الهامة داخل المجال. تتضمن الأمثلة OrderPlaced، وUserRegistered، وPaymentCompleted، وInvoiceGenerated، وSubscriptionCancelled.
غالبًا ما تتم معالجة المجال events باستخدام أنظمة تشبه observer. عندما يتم رفع المجال event، يمكن أن تتفاعل listener عن طريق إرسال الإشعارات أو تحديث قراءة models أو إنشاء السجلات أو بدء سير العمل.
وهذا يحافظ على تركيز منطق المجال الأساسي مع السماح بمعالجة الآثار الجانبية بشكل منفصل.
مثال من العالم الحقيقي: تم تقديم الطلب Observers
عند تقديم الطلب، قد تحدث العديد من الإجراءات:
- أرسل بريدًا إلكترونيًا لتأكيد الطلب.
- تقليل مخزون المنتج.
- إنشاء فاتورة.
- إخطار المستودع.
- تحديث نقاط العملاء.
- تحليلات المسار.
يسمح Observer Pattern بتنفيذ كل إجراء بشكل منفصل.
class OrderPlacedEvent
{
public function __construct(
public Order $order
) {
}
}
class SendOrderConfirmationListener
{
public function handle(OrderPlacedEvent $event): void
{
// Send confirmation email
}
}
class ReduceInventoryListener
{
public function handle(OrderPlacedEvent $event): void
{
// Reduce stock
}
}
class CreateInvoiceListener
{
public function handle(OrderPlacedEvent $event): void
{
// Create invoice
}
}يمكن أن يرسل رمز وضع الطلب event واحدًا، ويمكن أن تستجيب عدة listener بشكل مستقل.
Observer Pattern وQueues
يمكن لـ Observers أو listeners أحيانًا إجراء عمليات بطيئة، مثل إرسال رسائل البريد الإلكتروني، أو الاتصال بـ APIs، أو إنشاء ملفات PDF، أو معالجة الصور. قد يؤدي تشغيل كل هذه الإجراءات على الفور إلى إبطاء request الرئيسي.
في التطبيقات الحديثة، يمكن دمج observers مع queues. يتم تشغيل event على الفور، ولكن تتم معالجة بعض listener في الخلفية بواسطة عمال queue.
يؤدي هذا إلى الحفاظ على استجابة التطبيق مع السماح بحدوث إجراءات متعددة بعد event.
Observer Pattern وLoose Coupling
Loose coupling يعني أن classes تعتمد على بعضها البعض بأقل قدر ممكن. يدعم Observer Pattern loose coupling لأن subject لا يحتاج إلى معرفة تفاصيل concrete لكل observer.
يقوم subject بإعلام observers فقط من خلال نظام interface أو event الشائع. يمكن إضافة Observers أو إزالته أو تغييره دون تعديل subject.
وهذا يجعل النظام أكثر مرونة وأسهل للتوسيع.
Observer Pattern مقابل Strategy Pattern
يعد كل من Observer Pattern وStrategy Pattern من الأنماط السلوكية، لكنهما يحلان مشكلات مختلفة.
يتم استخدام Strategy Pattern عندما يحتاج التطبيق إلى اختيار سلوك أو خوارزمية واحدة من بين خيارات متعددة. على سبيل المثال، اختيار دفعة strategy أو خصم strategy.
يتم استخدام Observer Pattern عندما تحتاج كائنات متعددة إلى التفاعل مع event أو تغيير الحالة. على سبيل المثال، عندما يقوم مستخدم بالتسجيل، قد يستجيب العديد من observers.
باختصار، يختار Strategy سلوكًا واحدًا قابلاً للتبديل، بينما يقوم Observer بإعلام العديد من listeners بشيء حدث.
Observer Pattern مقابل Command Pattern
يقوم Command Pattern بتحويل request أو الإجراء إلى كائن. وهو مفيد لعمليات queues وundo وتنفيذ المهام وتسجيل الإجراءات.
يقوم Observer Pattern بإعلام observers عند حدوث event. يكون ذلك مفيدًا عند حدوث عدة تفاعلات مستقلة بعد event.
على سبيل المثال، قد يمثل SendWelcomeEmailCommand إجراءً واحدًا. قد يقوم UserRegisteredEvent بإخطار عدة listeners، يمكن لأحدها إرسال SendWelcomeEmailCommand.
باختصار، يمثل Command إجراءً، بينما يمثل Observer إشعارًا event.
Observer Pattern مقابل نمط الوسيط
يعمل نمط الوسيط على مركزية الاتصال بين الكائنات من خلال كائن وسيط. يكون مفيدًا عندما تتواصل العديد من الكائنات مع بعضها البعض بطرق معقدة.
يسمح Observer Pattern لـ observers بالاشتراك في subject أو event وتلقي الإشعارات. إنه يركز بشكل أكبر على التحديثات المستندة إلى event.
يعمل كلا النمطين على تقليل الاقتران المباشر، لكن الوسيط ينسق الاتصال، بينما يبث Observer تغييرات الحالة أو events.
فوائد Observer Pattern
يوفر Observer Pattern العديد من الفوائد في تصميم البرامج الموجهة للكائنات.
تشمل الفوائد الرئيسية ما يلي:
- يقلل tight coupling بين مصادر وتفاعلات event.
- يسمح للعديد من observers بالتفاعل مع نفس event.
- يدعم البنية التي تعتمد على event.
- يحافظ على نظافة منطق العمل الأساسية.
- يجعل من السهل إضافة تفاعلات جديدة دون تعديل الكود الموجودة.
- يحسن الفصل بين المسؤوليات.
- يعمل بشكل جيد مع queues ومعالجة الخلفية.
- يدعم إطار عمل أنظمة event مثل Laravel events وSymfony.
هذه الفوائد تجعل Observer Pattern مفيدًا في العديد من تطبيقات العالم الحقيقي.
عيوب Observer Pattern
يمكن أن يكون لـ Observer Pattern أيضًا عيوب. إحدى المشكلات هي أن السلوك قد يصبح من الصعب تتبعه. عند تشغيل event، قد يتم تشغيل عدة observers، وقد لا يكون واضحًا من الكود الرئيسي ما سيحدث بعد ذلك.
هناك مشكلة أخرى وهي طلب observer. إذا كان observers يعتمد على أمر معين، فقد يصبح النظام هشًا. ومن الناحية المثالية، يجب أن يكون observers مستقلاً.
يمكن أن تؤثر الأخطاء الموجودة داخل أحد observer أيضًا على عملية event إذا لم يتم التعامل معها بشكل صحيح. في الأنظمة الكبيرة، يصبح التسجيل ومعالجة الأخطاء وإعادة المحاولة وqueues أمرًا مهمًا.
متى يتم استخدام Observer Pattern
استخدم Observer Pattern عندما يؤدي تغيير event أو الحالة إلى حدوث تفاعلات مستقلة متعددة.
يكون Observer Pattern مفيدًا عندما:
- تحتاج الكائنات المتعددة إلى التفاعل عند حدوث شيء ما.
- تريد تجنب وضع العديد من الآثار الجانبية في خدمة واحدة.
- يمكن إضافة ردود فعل جديدة في المستقبل.
- يجب ألا يعرف subject جميع تفاصيل observer.
- أنت تقوم بإنشاء سير عمل يعتمد على event.
- أنت بحاجة إلى model observers أو event listeners أو أنظمة الإشعارات.
- يمكن التعامل مع التفاعلات البطيئة بشكل غير متزامن من خلال queues.
في حالة وجود هذه الشروط، يمكن لـ Observer Pattern أن يجعل التصميم أكثر وضوحًا ومرونة.
متى لا تستخدم Observer Pattern
لا تستخدم Observer Pattern عندما يجب أن يكون التدفق مباشرًا وبسيطًا للغاية. إذا حدث إجراء واحد فقط وكان ضروريًا لسير العمل الرئيسي، فقد يكون استدعاء الأسلوب المباشر أكثر وضوحًا.
تجنب Observer Pattern عندما:
- لا يوجد سوى رد فعل واحد بسيط.
- من شأن تدفق event أن يجعل فهم الكود أكثر صعوبة.
- Observers تعتمد بشكل كبير على أمر التنفيذ.
- يجب معالجة الأخطاء فورًا وبتسلسل صارم.
- يضيف النمط تعقيدًا غير ضروري لميزة صغيرة.
يجب أن يعمل Design patterns على تحسين الوضوح. إذا كان نظام observer يجعل التدفق مربكًا، فقد يكون النهج الأبسط هو الأفضل.
الأخطاء الشائعة في Observer Pattern
أحد الأخطاء الشائعة هو وضع منطق العمل المهم داخل observers. يعتبر Observers مفيدًا للآثار الجانبية وردود الفعل، لكن قواعد العمل الأساسية يجب أن تظل واضحة ويمكن تتبعها.
خطأ آخر هو جعل observers تعتمد على بعضها البعض. إذا كان يجب تشغيل observer قبل الآخر، فقد يتم تمثيل سير العمل بشكل أفضل كخدمة أو سلسلة command.
الخطأ الثالث هو عدم التعامل مع حالات فشل observer. إذا فشل إرسال البريد الإلكتروني، فهل يجب أن يفشل تسجيل المستخدم؟ تعتمد الإجابة على حالة العمل، ويجب على النظام التعامل معها عمدًا.
الخطأ الرابع هو إنشاء عدد كبير جدًا من event بأسماء غير واضحة. يجب أن تمثل أسماء Event إجراءات ذات معنى في النظام.
أفضل الممارسات لـ Observer Pattern
لاستخدام Observer Pattern بشكل فعال، يجب على المطورين الحفاظ على تركيز observers وأهمية event.
تتضمن أفضل الممارسات المفيدة ما يلي:
- استخدم أسماء event واضحة مثل UserRegistered أو OrderPlaced.
- اجعل كل observer يركز على مسؤولية واحدة.
- تجنب جعل observers تعتمد على بعضها البعض.
- استخدم queues لمكالمات observers البطيئة مثل البريد الإلكتروني أو مكالمات API.
- التعامل مع أخطاء observer عمدا.
- اجعل قواعد العمل الأساسية مرئية وقابلة للاختبار.
- توثيق events وlisteners المهمة في المشاريع الكبيرة.
- لا تستخدم observers لكل استدعاء أسلوب صغير.
تساعد هذه الممارسات في الحفاظ على الكود المستندة إلى event قابلة للصيانة ومفهومة.
قائمة مرجعية عملية قبل استخدام Observer Pattern
قبل استخدام Observer Pattern، يمكن للمطورين طرح هذه الأسئلة:
- هل يحتاج أحد event إلى إثارة تفاعلات متعددة؟
- هل ردود الفعل هذه مستقلة عن سير العمل الرئيسي؟
- هل سيتم إضافة تفاعلات جديدة لاحقاً؟
- هل يمكن اختبار observers بشكل منفصل؟
- هل يمكن أن تكون التفاعلات البطيئة queued؟
- هل سيؤدي هذا إلى تقليل الاقتران؟
- هل سيظل تدفق event مفهوماً؟
إذا كانت الإجابة بنعم على العديد من هذه الأسئلة، فقد يكون Observer Pattern اختيارًا جيدًا للتصميم.
الاستنتاج
Observer Pattern هو نمط تصميم سلوكي يسمح بإخطار الكائنات تلقائيًا عند تغيير حالة كائن آخر أو عند حدوث event مهم. وهو يدعم البنية المعتمدة على event ويساعد على فصل الإجراء الرئيسي عن التفاعلات الإضافية.
يعد Observer Pattern مفيدًا لتسجيل المستخدم ومعالجة الطلبات والإشعارات والتسجيل والتحليلات وmodel observers والمجال events وأنظمة event الإطارية مثل Laravel events و Symfony event المرسل.
ومع ذلك، يجب استخدام Observer Pattern بعناية. يمكن لعدد كبير جدًا من observers المخفية أن يجعل تتبع تدفق التطبيق أكثر صعوبة. عند تطبيقه بشكل صحيح، يعد Observer Pattern أداة قوية لإنشاء برامج موجهة للكائنات مرنة ومنفصلة وقابلة للصيانة.

