التعريف: يسمح لكائنات متعددة أن تتاح لها الفرصة لمعالجة الطلب ، وبالتالي تجنب علاقة الاقتران بين المرسل ومستقبل الطلب. قم بتوصيل هذه الكائنات بسلسلة وقم بتمرير الطلب على طول السلسلة حتى يعالجها كائن.
النوع: نمط سلوكي
مخطط الفصل:
دعونا أولاً نلقي نظرة على قطعة من الكود:
اختبار void العام (int i ، طلب طلب) {if (i == 1) {handler1.Response (request) ؛ } آخر إذا (i == 2) {handler2.response (request) ؛ } آخر إذا (i == 3) {handler3.response (request) ؛ } آخر إذا (i == 4) {handler4.response (request) ؛ } آخر {handler5.response (request) ؛ }} منطق العمل للرمز هو كما يلي: الطريقة لها معلمتان: عدد صحيح I وطلب طلب. وفقًا لقيمة I ، الذي سيتعامل مع الطلب ، إذا كنت == 1 ، فسيتم التعامل معها بواسطة Handler1 ، إذا كان i == 2 ، فسيتم التعامل معها بواسطة Handler2 ، وهكذا. في البرمجة ، يعد هذا النوع من طريقة معالجة الأعمال شائعة جدًا. جميع الفئات التي تتضمن طلبات المعالجة إذا ... أخرى ... بيانات الحكم الشرطية المرتبطة بسلسلة من المسؤولية لمعالجة الطلب. أعتقد أن الجميع يستخدمونها غالبًا. مزايا هذه الطريقة هي أنها بديهية للغاية وبسيطة وواضحة وسهلة الصيانة نسبيًا ، ولكن هذه الطريقة لديها أيضًا العديد من الصداع:
الكود المتضخم: في التطبيقات الفعلية ، عادة ما تكون شروط الحكم بسيطة للغاية لتحديد ما إذا كان 1 أو 2. قد يتطلب حسابات معقدة ، وربما الاستعلام عن قاعدة البيانات ، وما إلى ذلك. سيكون لهذا الكثير من التعليمات البرمجية الإضافية. إذا كان هناك العديد من شروط الحكم ، فإن هذا إذا ... آخر ... البيان مستحيل في الأساس قراءته.
درجة اقتران عالية: إذا أردنا الاستمرار في إضافة فصول تطلب ، يجب أن نستمر في إضافة آخر إذا كانت شروط الحكم ؛ بالإضافة إلى ذلك ، يتم كتابة ترتيب هذا الشرط أيضًا إلى الموتى. إذا أردنا تغيير الترتيب ، فيمكننا تعديل عبارة الشرط هذه فقط.
نظرًا لأننا فهمنا بالفعل أوجه القصور ، نحتاج إلى إيجاد طريقة لحلها. منطق العمل لهذا السيناريو بسيط للغاية: إذا تم استيفاء الحالة 1 ، فسيتم معالجتها بواسطة Handler1 ، وإذا لم يتم الوفاء بها ، فسيتم نقلها ؛ إذا تم استيفاء الحالة 2 ، فسيتم معالجتها بواسطة Handler2 ، وإذا لم يتم الوفاء بها ، فسيتم تمريرها ، وما إلى ذلك حتى نهاية الحالة. في الواقع ، فإن طريقة التحسين بسيطة للغاية ، والتي تتمثل في وضع جزء من شروط الحكم في فئة المعالجة. هذا هو مبدأ نموذج اتصال المسؤولية.
هيكل نموذج شركة المسؤولية
إن الرسم البياني للصف للنمط المتواصل مع المسؤولية بسيط للغاية ، وهو يتكون من فئة معالجتها بشكل مجردة ومجموعة من فئات التنفيذ:
فئة المعالجة التجريدية: تتضمن فئة المعالجة التجريدية بشكل أساسي nexthandler متغير عضو يشير إلى فئة المعالجة التالية وطريقة يسيطر على الطلب. الفكرة الرئيسية لطريقة Handrequest هي أنه إذا تم استيفاء شروط المعالجة ، فستتم معالجة فئة المعالجة هذه ، وإلا فإنه سيتم معالجته بواسطة Nexthandler.
فئة المعالجة المحددة: فئة المعالجة المحددة تنفذ بشكل أساسي منطق المعالجة المحدد والشروط القابلة للتطبيق للمعالجة.
مثال
نموذج سلسلة المسؤولية له دوران:
دور المعالج التجريدي: يحدد واجهة مطلوبة. إذا لزم الأمر ، يمكنك تحديد طريقة لتعيين وإعادة الإشارة إلى كائن المنزل التالي.
دور ConcreteHandler: إذا كان من الممكن معالجته ، قم بمعالجة الطلب. إذا لم يكن من الممكن معالجته ، فقم بتمرير الطلب إلى المنزل التالي واترك المنزل التالي يتعامل معه. وهذا يعني أنه يتعامل مع الطلبات التي يمكنها التعامل معها ويمكنها الوصول إلى منزلها التالي.
رمز الاختبار للنمط أعلاه هو كما يلي:
package chainofresp ؛/***الوصف: دور المعالجة التجريدية*/معالج فئة التجريد العامة {محمية معالج الخلف ؛ / ***الوصف: طريقة المعالجة*/ معالج الفراغ التجريدي العام (حالة السلسلة) ؛ المعالج العام getSuccessor () {عودة خليفة ؛ } public void setSuccessor (Calller Sivers) {this.successor = suckor ؛ }} حزمة chainofresp ؛/***الوصف: معالجة مفصلة للأدوار*/الفئة العامة concreteHandler1 يمتد المعالج {Override public void handlerRequest (حالة السلسلة) {// إذا كانت مسؤوليتك الخاصة ، سوف تتعامل معها وتكون مسؤولاً عن تمريرها إلى المنزل التالي إذا (cyncreteHandler1)) يعود ؛ } آخر {system.out.println ("ConcreteHandler1 seded") ؛ GetSuccessor (). HandlerRequest (حالة) ؛ }}} package chainofresp ؛/***الوصف: معالجة مفصلة للأدوار*/الفئة العامة concreteHandler2 يمتد معالج {Override public void handlerRequest (حالة السلسلة) {// إذا كانت مسؤوليتك الخاصة ، سوف تتعامل معها وتكون مسؤولاً عن نقلها إلى المنزل التالي إذا (cyncreteHandler2)) يعود ؛ } آخر {system.out.println ("concreteHandler2 seded") ؛ GetSuccessor (). HandlerRequest (حالة) ؛ }}} حزمة chainofresp ؛/*** الوصف: دور معالجة مفصل*/فئة عامة ، يمتد ConcreteHandlern المعالج {/*** هنا يُفترض أن n هي العقدة الأخيرة من السلسلة التي يجب معالجتها* في المواقف الفعلية ، قد تظهر حلقة أو شجرة ،* هذا ليس بالضرورة العقدة الأخيرة. * */ Override public void handlerRequest (string string) {system.out.println ("ConcreteHandlern Handled") ؛ }} package chainofresp ؛/***الوصف: اختبار الفئة*/عميل الفئة العامة {/***الوصف:*/public static void main (string [] args) {Handler Handler1 = new ConcreteHandler1 () ؛ Handler Handler2 = New ConcreteHandler2 () ؛ معالج المعالج = جديد concreteHandlern () ؛ // chain handler1.SetSuccessor (Handler2) ؛ Handler2.Setsuccessor (معالجة) ؛ //لنفترض أن هذا الطلب هو مسؤولية ConcreteHandler2 Handler1.HandlerRequest ("ConcreteHandler2") ؛ }}
لإعطاء هذا المثال ، في ورشة الإنتاج لمصنع الألعاب ، يعد خط التجميع سلسلة من المسؤولية. إذا كانت طائرة لعبة تحتوي على مجموعة شل ، ومجموعة المحرك ، ومجمع المروحة ، و Packer النموذجية. عندما تتدفق الطائرة إلى أي شخص يتدفق إليه ، سيكون مسؤولاً عن تثبيت الجزء الذي يتحمله. بعد تثبيت هذا الجزء ، سوف يتدفق إلى الخطوة التالية ويعرف أن جميع البيئات قد اكتملت. هذه سلسلة من المسؤولية التي تم إنشاؤها. هناك أيضًا سلسلة تفتيش جودة ، تنقسم إلى أجزاء متعددة ، وفحص الصدفة ، وفحص المحرك ، وفحص المروحة ، وفحص التغليف. عندما يتم ترك المنتج للمفتش لاختبار القطعة التي يتحملها ، إذا كانت هناك مشكلة ، فسيتم إخراجها مباشرة. إذا لم تكن هناك مشكلة ، فسيتم نقلها إلى المفتش التالي حتى يتم الانتهاء من جميع الاختبارات. هذان السلاسل من المسؤولية ، ولكن الفرق هو أن الجميع سيعالج سلسلة المسؤولية ومعالجة جزء منه ؛ بينما بعد الحكم ، سيتم معالجة سلسلة المسؤولية عن فحص الجودة أو عدم معالجتها. هذه هي الفئتين من سلاسل المسؤولية. هذا الأخير يسمى سلاسل المسؤولية الخالصة ، ويسمى السابق سلاسل المسؤولية الناقص. نادراً ما توجد سلاسل المسؤولية الخالصة في التطبيقات العملية. الشائع هو سلاسل المسؤولية الناقص. يحاكي النموذج أعلاه سلاسل المسؤولية الخالصة للتعامل معها.
إيجابيات وسلبيات نموذج سلسلة المسؤولية
بالمقارنة مع إذا ... آخر ... ، فإن نمط سلسلة المسؤولية لديه قدرة اقتران أقل لأنه يوزع الأحكام المشروطة في فئات المعالجة المختلفة ، ويمكن تعيين ترتيب المعالجة الأولوية لفئات المعالجة هذه حسب الرغبة. يحتوي نموذج سلسلة المسؤولية أيضًا على عيوبه ، وهو نفس البيان IF ... آخر ... ، أي قبل العثور على فئة المعالجة الصحيحة ، يجب تنفيذ جميع شروط الحكم. عندما تكون سلسلة المسؤولية طويلة نسبيًا ، تكون مشكلة الأداء أكثر خطورة.
السيناريوهات المعمول بها لسلسلة مسؤولية نموذج المسؤولية
تمامًا مثل مثال البداية ، إذا كنت تشعر بالإرهاق عند استخدام بيان IF ... آخر ... لتنظيم سلسلة من المسؤولية ويبدو الكود سيئًا ، فيمكنك استخدام سلسلة المسؤولية لإعادة تشكيلها.
لخص
نموذج سلسلة المسؤولية هو في الواقع نسخة مرنة من IF ... آخر ... بيان. إنه يضع شروط الحكم هذه في كل فئة معالجة. ميزة ذلك هي أنها أكثر مرونة ، ولكنها تجلب أيضًا المخاطر. على سبيل المثال ، عند إعداد العلاقة بين فئة المعالجة قبل وبعد فئة المعالجة ، يجب أن تكون حريصًا جدًا على الحكم على العلاقة بين المنطق الشرطي قبل وبعد فئة المعالجة ، وتحرز على عدم وجود مراجع دائرية في السلسلة.