Base/Knowledges/IT/Рефакторинг/Методы рефакторинга/Замена подкласса делегатом (Replace Subclass with Delegate).md
2026-02-23 19:52:05 +03:00

4.2 KiB
Raw Blame History

#рефакторинг #методы_рефакторинга

!Pasted image 20250220082420.png

Проблема

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

class Order {
  get daysToShip() {
    return this._warehouse.daysToShip;
  }
}

class PriorityOrder extends Order {
  get daysToShip() {
    return this._priorityPlan.daysToShip;
  }
}

Решение

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

class Order {
  get daysToShip() {
    return (this._priorityDelegate)
      ? this._priorityDelegate.daysToShip
      : this._warehouse.daysToShip;
  }
}

class PriorityOrderDelegate {
  get daysToShip() {
    return this._priorityPlan.daysToShip
  }
}

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

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

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

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

Достоинства

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

Недостатки

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

  1. Создайте поле в подклассе для содержания суперкласса. На первом этапе поместите в него текущий объект.
  2. Измените методы подкласса так, чтобы они использовали объект суперкласса, вместо this.
  3. Для методов, которые были унаследованы из суперкласса и которые вызываются в клиентском коде, в подклассе нужно создать простые делегирующие методы.
  4. Уберите объявление наследования из подкласса
  5. Измените код инициализации поля, в котором хранится бывший суперкласс, созданием нового объекта

Обратный рефакторинг

Ссылки