استبدال التوريث بالتفويض (Replace Inheritance with Delegation)
المشكلة
يستخدم صنف فرعي جزءًا فقط من توابع صنفه الأب (أو من غير الممكن وراثة بيانات الصنف الأب).
الحل
إنشاء حقل ووضع كائن صنف أب فيه، وتفويض التوابع إلى كائن الصنف الأب، والتخلص من التوريث.
مثال
قبل إعادة التصميم
يستخدم الصنف الفرعي Stack
جزءًا من توابع صنفه الأب Vector
:
بعد إعادة التصميم
إنشاء الحقل vector
في الصنف Stack
ووضع كائن للصنف الأب Vector
فيه وتفويض التابع ()isEmpty
إليه والتخلص من التوريث:
لم إعادة التصميم؟
يمكن أن يحسّن استبدال التوريث بالتكوين من تصميم الصنف تحسينًا كبيرًا إذا:
- انتهك الصنف الفرعي مبدأ ليسكوف للتعويض (Liskov substitution principle)، أي إذا كان التوريث يتحقق فقط لدمج الشيفرة المشتركة ولكن ليس لأن الصنف الفرعي هو امتداد للصنف الأب.
- يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الأب. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ أبٍ لم يكن من المفترض استدعاءه.
في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف الأب، لن يكون للصنف الفرعي سوى التوابع اللازمة لتفويض توابع كائن الصنف الأب.
فوائد تطبيق الحل
- لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الأب.
- يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم الاستراتيجية.
مساوئ تطبيق الحل
- يجب كتابة العديد من توابع التفويض البسيطة.
آلية الحل
- أنشئ حقلًا في الصنف الفرعي لحفظ الصنف الأب فيه. خلال المرحلة الأولية، ضع الكائن الحالي فيه.
- غيّر توابع الصنف الفرعي بحيث تستخدم كائن الصنف الأب بدلًا من الكائن
this
. - بالنسبة للتوابع الموروثة من الصنف الأب المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي.
- أزل تعريف التوريث من الصنف الفرعي.
- غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الأب السابق عن طريق إنشاء كائن جديد.
انظر أيضًا
مصادر
صفحة توثيق استبدال التوريث بالتفويض في موقع refactoring.guru.