تغليف المجموعات (Encapsulate Collection)
المشكلة
صنف يحتوي على حقل مجموعة وجالب (getter) وضابط (setter) بسيط للعمل مع المجموعة.
الحل
ضبط القيمة المعادة من الجالب لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.
مثال
قبل إعادة التصميم
يحتوي الصنف Person
على جالب getCourses
وضابط setCourses
بسيطين للتحكم بالدروس التي سجل بها الشخص:
بعد إعادة التصميم
ضبط القيمة المعادة من الجالب setCourses
لتصبح للقراءة فقط وإضافة تابعين جديدين أحدهما لإضافة دروس جديدة للشخص (أي addCourses
)، والآخر لحذف دروس محددة (أي removeCourses
):
لم إعادة التصميم؟
يحتوي الصنف على حقل يحتوي بدوره على مجموعة من الكائنات. يمكن أن تكون هذه المجموعة مصفوفة أو قائمة أو مجموعة أو مُتجه (vector). يُنشَأ جالب وضابط طبيعي للعمل مع المجموعة.
ولكن يجب استخدام المجموعات بواسطة بروتوكول يختلف قليلا عن الذي تستخدمه أنواع البيانات الأخرى. لا يجب أن يُعيد التابع الجالب كائن المجموعة ذاته، لأن هذا سيسمح للعملاء بتغيير محتويات المجموعة بدون معرفة صنف المالك. بالإضافة إلى ذلك، سيظهر هذا الكثيرَ من الهياكل الداخلية لبيانات الكائن إلى العملاء. ويجب أن يُعيد تابع الحصول على عناصر المجموعة قيمة لا تسمح بتغيير المجموعة أو كشف المزيد من البيانات عن هيكلها.
بالإضافة إلى ذلك، يجب ألَّا يكون هناك تابع يحدد قيمة للمجموعة. بدلًا من ذلك ينبغي أن تكون هناك عمليات لإضافة العناصر وحذفها. بفضل هذا، يتحكم الكائن المالك في إضافة عناصر المجموعة وحذفها.
يُغلِّف مثل هذا البروتوكول المجموعة بشكل صحيح، مما يقلل في النهاية من درجة الارتباط بين الصنف المالك وشيفرة العميل.
فوائد تطبيق الحل
- تغليف حقل المجموعة داخل صنف. عند استدعاء الجالب، يُعيد نسخة من المجموعة، الأمر الذي يمنع التغيير العرضي أو الكتابة فوق عناصر المجموعة بدون معرفة الصنف الذي يحتوي على المجموعة.
- إذا كانت عناصر المجموعة موجودة داخل نوع بسيط، مثل مصفوفة، فإنك بذلك تُنشئ توابعًا أكثر ملاءمة للعمل مع المجموعة.
- إذا كانت عناصر المجموعة موجودة داخل حاوية غير بسيطة (صنف المجموعة القياسية)، بواسطة تغليف المجموعة، فيمكن تقييد الوصول إلى التوابع القياسية غير المرغوب فيها للمجموعة (مثل تقييد إضافة عناصر جديدة).
آلية الحل
- أنشئ توابعًا لإضافة وحذف عناصر المجموعة. ويجب أن يقبلوا عناصر المجموعة في مُعامِلاتهم.
- تعيين مجموعة فارغة إلى الحقل كقيمة أولية إذا لم يتم ذلك في مُنشِئ الصنف.
- ابحث عن استدعاءات ضابط حقل المجموعة. تغيير الضابط بحيث انه يستخدم عمليات لإضافة وحذف العناصر، أو حمل هذه العمليات على استدعاء الشيفرة البرمجية للعميل. علمًا بأنه يمكن استخدام الضوابط فقط لاستبدال كافة عناصر المجموعة بأخرى. ولذلك قد يكون من المستحسن تغيير اسم الضابط (تابع إعادة التسمية Rename) إلى
replace
. - ابحث عن استدعاءات جالب المجموعة والتي تتغير بعدها المجموعة. غَيِّر الشيفرة البرمجية بحيث تستخدم التوابع الجديدة لإضافة وحذف عناصر من المجموعة.
- غَيِّر الجالب، وبذلك يُعيد تمثيل قابل للقراءة فقط للمجموعة.
- افحص الشيفرة البرمجية للعميل التي تستخدم المجموعة للشيفرة البرمجية التي قد تبدو أفضل داخل صنف المجموعة نفسها.