سؤال

في نظام الحصول على الإشارة الرقمية، غالبًا ما يتم دفع البيانات إلى مراقب في النظام بواسطة خيط واحد.

مثال من ويكيبيديا/Observer_pattern:

foreach (IObserver observer in observers)
    observer.Update(message);

عندما على سبيل المثال.إجراء المستخدم من على سبيل المثال.يتطلب مؤشر ترابط واجهة المستخدم الرسومية توقف تدفق البيانات، وتريد قطع الاتصال بين الموضوع والمراقب، وحتى التخلص من المراقب تمامًا.

قد يجادل المرء:يجب عليك فقط إيقاف مصدر البيانات، والانتظار حتى تظهر قيمة خافرة للتخلص من الاتصال.ولكن هذا من شأنه أن يؤدي إلى مزيد من الكمون في النظام.

بالطبع، إذا طلب مؤشر ترابط ضخ البيانات عنوان المراقب، فقد يجد أنه يرسل رسالة إلى كائن مدمر.

هل قام شخص ما بإنشاء نمط تصميم "رسمي" لمواجهة هذا الموقف؟أليس كذلك؟

هل كانت مفيدة؟

المحلول

إذا كنت تريد أن يكون مصدر البيانات دائمًا في الجانب الآمن من التزامن، فيجب أن يكون لديك مؤشر واحد على الأقل يكون آمنًا دائمًا لاستخدامه.لذلك يجب أن يكون لكائن المراقب عمر لا ينتهي قبل عمر مصدر البيانات.

يمكن القيام بذلك عن طريق إضافة المراقبين فقط، ولكن لا يمكن إزالتهم مطلقًا.يمكنك جعل كل مراقب لا يقوم بالتنفيذ الأساسي بنفسه، ولكن يمكنك تفويض هذه المهمة إلى كائن ObserverImpl.يمكنك قفل الوصول إلى هذا الكائن ضمنا.هذه ليست مشكلة كبيرة، بل تعني فقط أنه سيتم حظر إلغاء الاشتراك في واجهة المستخدم الرسومية لفترة قصيرة في حالة انشغال المراقب باستخدام كائن ObserverImpl.إذا كانت استجابة واجهة المستخدم الرسومية تمثل مشكلة، فيمكنك استخدام نوع ما من آلية قائمة انتظار المهام المتزامنة مع دفع مهمة إلغاء الاشتراك إليها.(مثل PostMessage في نظام التشغيل Windows)

عند إلغاء الاشتراك، ما عليك سوى استبدال التطبيق الأساسي بتطبيق وهمي.مرة أخرى، يجب أن تمسك هذه العملية بالقفل.سيؤدي هذا بالفعل إلى بعض الانتظار لمصدر البيانات، ولكن نظرًا لأنه مجرد [قفل - مؤشر مبادلة - إلغاء القفل] يمكنك القول أن هذا سريع بما يكفي لتطبيقات الوقت الفعلي.

إذا كنت تريد تجنب تكديس كائنات Observer التي تحتوي فقط على دمية، فيجب عليك القيام بنوع من مسك الدفاتر، ولكن هذا قد يتلخص في شيء تافه مثل كائن يحمل مؤشرًا إلى كائن Observer الذي يحتاجه من القائمة.

تحسين :إذا احتفظت أيضًا بالتطبيقات (التطبيق الحقيقي + الوهمي) على قيد الحياة طالما أن المراقب نفسه، فيمكنك القيام بذلك دون قفل فعلي، واستخدام شيء مثل InterlockedExchangePointer لتبديل المؤشرات.السيناريو الأسوأ :يتم إجراء تفويض المكالمة أثناء تبديل المؤشر -> ليس هناك مشكلة كبيرة، حيث تظل جميع الكائنات حية ويمكن متابعة التفويض.سيكون استدعاء التفويض التالي لكائن التنفيذ الجديد.(باستثناء أي مقايضات جديدة بالطبع)

نصائح أخرى

يمكنك إرسال رسالة إلى جميع المراقبين لإبلاغهم بأن مصدر البيانات قد انتهى والسماح للمراقبين بإزالة أنفسهم من القائمة.

ردًا على التعليق، يجب أن يسمح تنفيذ نمط الموضوع والمراقب بإضافة/إزالة المراقبين بشكل ديناميكي.في لغة C#، نظام الأحداث هو نمط موضوع/مراقب حيث يتم إضافة المراقبين باستخدامه event += observer وإزالتها باستخدام event -= observer.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top