Friend spotlight!
Whimsical Animations course
Friend spotlight!
NEW Whimsical Animations course
Friend spotlight! NEW Whimsical Animations course
huge discount only this week
Friend spotlight! Want to make your project stand out? NEW Whimsical Animations course huge discount only this week

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

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

Проблема

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

Решение

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

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

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

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

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

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

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

Достоинства

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

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

Недостатки

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

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

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

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

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

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

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