Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!

Замена наследования делегированием

Также известен как: Replace Inheritance with Delegation

Проблема

У вас есть подкласс, который использует только часть методов суперкласса или не хочет наследовать его данные.

Решение

Создайте поле и поместите в него объект суперкласса, делегируйте выполнение методов объекту-суперклассу, уберите наследование.

До
Replace Inheritance with Delegation - Before
После
Replace Inheritance with Delegation - After

Причины рефакторинга

Замена наследования композицией может значительно улучшить дизайн классов, если:

  • Ваш подкласс нарушает принцип замещения Барбары Лисков. Другими словами, наследование возникло только ради объединения общего кода, но не потому, что подкласс «является» (is-a) расширением суперкласса.

  • Подкласс использует только часть методов суперкласса. В этом случае, это только вопрос времени, пока кто-то не вызовет метод суперкласса, который он не должен был вызывать.

Суть рефакторинга сводится к тому, чтобы разделить оба класса, и сделать суперкласс помощником подкласса, а не его родителем. Вместо того чтобы наследовать все методы суперкласса, подкласс будет иметь только необходимые методы, которые будут делегировать выполнение методам объекта-суперкласса.

Достоинства

  • Класс не содержит лишних методов, которые достались ему в наследство от суперкласса.

  • В поле-делегат можно подставлять разные объекты, имеющие различные реализации функциональности. По сути, вы получаете реализацию паттерна проектирования Стратегия.

Недостатки

  • Приходится писать очень много простых делегирующих методов.

Порядок рефакторинга

  1. Создайте поле в подклассе для содержания суперкласса. На первом этапе поместите в него текущий объект.

  2. Измените методы подкласса так, чтобы они использовали объект суперкласса, вместо this.

  3. Для методов, которые были унаследованы из суперкласса и которые вызываются в клиентском коде, в подклассе нужно создать простые делегирующие методы.

  4. Уберите объявление наследования из подкласса.

  5. Измените код инициализации поля, в котором хранится бывший суперкласс, созданием нового объекта.