نمط الوسيط
في هندسة البرمجيات ، يحدد نمط الوسيط كائنًا يغلف كيفية تفاعل مجموعة من الكائنات. ويعتبر هذا النمط نمطًا سلوكيًا نظرًا للطريقة التي يمكنه بها تغيير سلوك تشغيل البرنامج.
في البرمجة الموجهة للكائنات، تتكون البرامج غالبًا من العديد من الفئات . يتم توزيع منطق الأعمال والحساب بين هذه الفئات. ومع ذلك، مع إضافة المزيد من الفئات إلى البرنامج، وخاصة أثناء الصيانة و/أو إعادة الهيكلة ، قد تصبح مشكلة الاتصال بين هذه الفئات أكثر تعقيدًا. وهذا يجعل قراءة البرنامج وصيانته أكثر صعوبة. علاوة على ذلك، قد يصبح من الصعب تغيير البرنامج، حيث أن أي تغيير قد يؤثر على الكود في العديد من الفئات الأخرى.
مع نمط الوسيط، يتم تغليف الاتصال بين الكائنات داخل كائن وسيط . لم تعد الكائنات تتواصل مباشرة مع بعضها البعض، بل تتواصل بدلاً من ذلك من خلال الوسيط. وهذا يقلل من التبعيات بين الكائنات المتواصلة، وبالتالي يقلل من الاقتران .
ملخص
نمط تصميم الوسيط [1] هو أحد أنماط التصميم الثلاثة والعشرين المعروفة التي تصف كيفية حل مشاكل التصميم المتكررة لتصميم برمجيات موجهة للكائنات مرنة وقابلة لإعادة الاستخدام، أي الكائنات التي يسهل تنفيذها وتغييرها واختبارها وإعادة استخدامها.
المشاكل التي يمكن أن يحلها نمط تصميم الوسيط[2]
- ينبغي تجنب الاقتران الوثيق بين مجموعة من الكائنات المتفاعلة.
- يجب أن يكون من الممكن تغيير التفاعل بين مجموعة من الكائنات بشكل مستقل.
إن تعريف مجموعة من الكائنات المتفاعلة من خلال الوصول إلى بعضها البعض وتحديثها بشكل مباشر أمر غير مرن لأنه يربط الكائنات ببعضها البعض بشكل وثيق ويجعل من المستحيل تغيير التفاعل بشكل مستقل عن الكائنات (دون الحاجة إلى تغييرها). كما يمنع الكائنات من إعادة الاستخدام ويجعل من الصعب اختبارها.
من الصعب تنفيذ الكائنات المرتبطة بشكل وثيق وتغييرها واختبارها وإعادة استخدامها لأنها تشير إلى العديد من الكائنات المختلفة وتعرف عنها.
الحلول التي وصفها نمط تصميم الوسيط
- تعريف كائن منفصل (وسيط) يغلف التفاعل بين مجموعة من الكائنات.
- تفوض الكائنات تفاعلها إلى كائن وسيط بدلاً من التفاعل مع بعضها البعض بشكل مباشر.
تتفاعل الكائنات مع بعضها البعض بطريقة غير مباشرة من خلال كائن وسيط يتحكم وينسق التفاعل.
وهذا يجعل الكائنات مرتبطة بشكل فضفاض . فهي تشير فقط إلى كائن الوسيط الخاص بها وتعرفه ولا تملك أي معرفة صريحة ببعضها البعض.
انظر أيضًا إلى مخطط فئة UML وتسلسلها أدناه.
تعريف
إن جوهر نمط الوسيط هو "تعريف كائن يغلف كيفية تفاعل مجموعة من الكائنات". وهو يعزز الاقتران الفضفاض من خلال منع الكائنات من الإشارة إلى بعضها البعض صراحةً، ويسمح بتنويع تفاعلها بشكل مستقل. [3] [4] يمكن لفئات العميل استخدام الوسيط لإرسال رسائل إلى عملاء آخرين، ويمكنها تلقي رسائل من عملاء آخرين عبر حدث على فئة الوسيط.
بناء
مخطط فئة وتسلسل UML

في مخطط فئة UML أعلاه ، لا تشير الفئات و إلى بعضها البعض (ولا تقوم بتحديثها) بشكل مباشر. بدلاً من ذلك، تشير إلى الواجهة المشتركة للتحكم في التفاعل وتنسيقه ( )، مما يجعلها مستقلة عن بعضها البعض فيما يتعلق بكيفية تنفيذ التفاعل. تنفذ الفئة التفاعل بين و .
Colleague1Colleague2Mediatormediate()Mediator1Colleague1Colleague2
يوضح مخطط تسلسل UML التفاعلات أثناء التشغيل. في هذا المثال، يتوسط الكائن (يتحكم وينسق) التفاعل بين كائنين .
Mediator1Colleague1Colleague2
بافتراض أن Colleague1يريد التفاعل مع Colleague2(لتحديث/مزامنة حالته، على سبيل المثال)، Colleague1فإنه يستدعي mediate(this)الكائن Mediator1، الذي يحصل على البيانات المتغيرة منه Colleague1ويقوم بإجراء عملية action2()عليه Colleague2.
بعد ذلك،
Colleague2يتم استدعاء mediate(this)الكائن Mediator1، الذي يحصل على البيانات المتغيرة منه Colleague2ويقوم بإجراء عملية action1()عليه Colleague1.
مخطط الفصل

- مشاركون
الوسيط - يحدد واجهة الاتصال بين كائنات الزملاء
ConcreteMediator - ينفذ واجهة الوسيط وينسق الاتصال بين كائنات الزملاء . وهو على علم بجميع الزملاء وأغراضهم فيما يتعلق بالاتصال المتبادل.
زميل - يحدد واجهة الاتصال مع الزملاء الآخرين من خلال الوسيط الخاص به
ConcreteColleague - ينفذ واجهة Colleague ويتواصل مع الزملاء الآخرين من خلال الوسيط الخاص به
مثال
سي شارب
يضمن نمط الوسيط أن المكونات مقترنة بشكل فضفاض ، بحيث لا تستدعي بعضها البعض صراحةً، بل تفعل ذلك بدلاً من ذلك من خلال استدعاءات إلى وسيط. في المثال التالي، يسجل الوسيط جميع المكونات ثم يستدعي طرق SetState الخاصة بها.
واجهة IComponent { void SetState ( حالة الكائن ); }
الفئة Component1 : IComponent { void داخلي SetState ( حالة الكائن ) { رمي استثناء NotImplementedException (); } }
الفئة Component2 : IComponent { void داخلي SetState ( حالة الكائن ) { رمي استثناء NotImplementedException (); } }
// يتوسط المهام المشتركة
class Mediator { internal IComponent Component1 { get ; set ; } internal IComponent Component2 { get ; set ; }
void داخلي ChangeState ( حالة الكائن ) { this.Component1.SetState ( حالة ) ؛ this.Component2.SetState ( حالة ) ؛ } }
يمكن لغرفة الدردشة استخدام نمط الوسيط، أو نظام حيث يتلقى العديد من "العملاء" رسالة في كل مرة يقوم فيها أحد العملاء الآخرين بإجراء ما (بالنسبة لغرف الدردشة، سيكون هذا عندما يرسل كل شخص رسالة). في الواقع، لن يكون استخدام نمط الوسيط لغرفة الدردشة عمليًا إلا عند استخدامه مع الاتصال عن بُعد . لن يسمح استخدام المقابس الخام باستدعاءات المندوب (الأشخاص المشتركين في حدث MessageReceived لفئة الوسيط).
المندوب العام void MessageReceivedEventHandler ( سلسلة الرسالة ، سلسلة المرسل )؛
الفئة العامة Mediator { الحدث العام MessageReceivedEventHandler MessageReceived ؛
public void Send ( سلسلة رسالة ، سلسلة مرسل ) { إذا ( رسالة مستلمة ! = لا شيء ) { Console.WriteLine ( " إرسال '{0}' من {1}" ، رسالة ، مرسل )؛ MessageReceived ( رسالة ، مرسل )؛ } } }
الفئة العامة Person { الوسيط الخاص _mediator ؛
سلسلة عامة الاسم { get ; set ; }
public Person ( Mediator mediator ، string name ) { Name = name ؛ _mediator = mediator ؛ _mediator . MessageReceived += new MessageReceivedEventHandler ( Receive )؛ }
private void Receive ( string message , string sender ) { if ( sender != Name ) Console.WriteLine ( " {0} received '{1}' from {2}" , Name , message , sender ) ; }
public void Send ( سلسلة رسالة ) { _mediator.Send ( رسالة ، اسم ) ؛ } }
جافا
في المثال التالي، Mediatorيتحكم كائن في قيم العديد من Storageالكائنات، مما يجبر كود المستخدم على الوصول إلى القيم المخزنة من خلال الوسيط. عندما يريد كائن التخزين إصدار حدث يشير إلى أن قيمته قد تغيرت، فإنه يعود أيضًا إلى كائن الوسيط (عبر الطريقة notifyObservers) الذي يتحكم في قائمة المراقبين (يتم تنفيذه باستخدام نمط المراقب ).
استيراد java.util.HashMap ؛ استيراد java.util.Optional ؛ استيراد java.util.concurrent.CopyOnWriteArrayList ؛ استيراد java.util.function.Consumer ؛
الفئة Storage < T > { قيمة T ؛ T getValue ( ) { قيمة الإرجاع ؛ } void setValue ( وسيط < T > mediator ، سلسلة storageName ، قيمة T ) { this.value = value ؛ mediator.notifyObservers ( اسم التخزين ) ؛ } }
class Mediator < T > { private final HashMap < String , Storage < T >> storageMap = new HashMap < > (); private final CopyOnWriteArrayList < Consumer < String >> observers = new CopyOnWriteArrayList < > (); public void setValue ( String storageName , T value ) { Storage storage = storageMap.computeIfAbsent ( storageName , name - > new Storage <> ()) ; storage.setValue ( this , storageName , value ) ; } public Optional < T > getValue ( String storageName ) { return Optional.ofNullable ( storageMap.get ( storageName ) ) . map ( Storage :: getValue ) ; } public void addObserver ( String storageName , Runnable observer ) { observers.add ( eventName - > { if ( eventName.equals ( storageName ) ) { observer.run ( ) ; } } ) ; } void notifyObservers ( String eventName ) { observers.forEach ( observer - > observer.accept ( eventName ) ) ; } }
public class MediatorDemo { public static void main ( String [] args ) { Mediator < Integer > mediator = new Mediator <> (); mediator . setValue ( "bob" ، 20 ); mediator . setValue ( "alice" ، 24 ); mediator . getValue ( "alice" ). ifPresent ( age -> System . out . println ( "age for alice: " + age )); mediator . addObserver ( "bob" ، () -> { System . out . println ( "new age for bob: " + mediator . getValue ( "bob" ). orElseThrow ( RuntimeException :: new )); }); mediator . setValue ( "bob" ، 21 ); } }
انظر أيضا
- وساطة البيانات
- أنماط التصميم ، الكتاب الذي أدى إلى دراسة أنماط التصميم في علوم الكمبيوتر [ بحاجة لمصدر ]
- نمط تصميم البرمجيات ، حل قياسي للمشاكل الشائعة في تصميم البرمجيات
مراجع
- ^ إيريك جاما، ريتشارد هيلم، رالف جونسون، جون فليسايدس (1994). أنماط التصميم: عناصر البرمجيات الموجهة للكائنات القابلة لإعادة الاستخدام . أديسون ويسلي. ص 273 وما يليه. رقم ISBN 0-201-63361-2.
{{cite book}}:CS1 maint: أسماء متعددة: قائمة المؤلفين ( الرابط ) - ^ فرانك، غونتر. "نمط تصميم الوسيط - المشكلة والحل والتطبيق". w3sDesign . تم الاسترجاع في 12 أغسطس 2017 .
- ^ جاما، إيريش ؛ هيلم، ريتشارد؛ جونسون، رالف ؛ فليسيدس، جون (1994). أنماط التصميم . أديسون ويسلي . ISBN 0-201-63361-2.
- ^ "نمط تصميم الوسيط". SourceMaking .
- ^ فرانك، غونتر. "نمط تصميم الوسيط - البنية والتعاون". w3sDesign . تم الاسترجاع في 12 أغسطس 2017 .
روابط خارجية
- كايزر، بودو (2012-09-21). "هل يُنصح باستخدام نمط الوسيط؟". Stack Overflow .
