Логотип ConstructiCat
CodeBust.
Навигация по разделу ▾

Извлечение подкласса.

Проблема

Класс имеет фичи, которые используются только в определённых случаях.

Решение

Создайте подкласс и используйте его в этих случаях.

##Пример

До
class JobItem {
  int unitPrice;
  int quantity;
  Employee employee;

  int getUnitPrice() {
    return employee != null ? employee.getRate() : unitPrice;
  }
}
После
class JobItem {
  int unitPrice;
  int quantity;

  int getUnitPrice() { return unitPrice; }
}
class LaborItem extends JobItem {
  Employee employee;

  int getUnitPrice() { return employee.getRate(); }
}

##Зачем делать рефакторинг

В основном классе находятся методы и поля для реализации какого-то редкого случая использования класса. Этот случай, хоть и очень редкий, является частью обязанностей класса, поэтому все связанные с ним поля и методы неправильно было бы вынести в абсолютно другой класс. Но, с другой стороны, их можно вынести в подкласс с помощью этого рефакторинга.

##Преимущества

  • Создать подкласс довольно легко и быстро.

  • Можно выделить несколько разных подклассов, если основной класс реализует несколько подобных особых случаев.

##Как делать рефакторинг

  1. Создайте новый подкласс из интересующего вас класса.

  2. Если для создания объектов из подкласса будут нужны какие-то дополнительные данные, создайте конструктор и дополните его нужными параметрами. Не забудьте вызвать родительскую реализацию конструктора.

  3. Найдите все вызовы конструктора родительского класса. В тех случаях, когда требуется функциональность подкласса, замените родительский конструктор конструктором подкласса.

  4. Переместите нужные методы и поля из родительского класса в подкласс. Используйте для этого спуск метода и спуск поля. Проще всего начинать перенос с методов. Так поля будут доступны для них все время: из родительского класса до переноса, и из самого подкласса после окончания переноса.

  5. После того как подкласс готов, найдите все старые поля, которые управляли тем, какой набор функций должен выполняться. Эти поля можно удалить, заменив полиморфизмом все условные операторы, в которых они использовались. Простой пример — у вас в классе Автомобиль было поле isElectricCar, и в зависимости от него, в методе refuel() в машину либо заливается бензин, либо заряжается электричество. В результате рефакторинга, поле isElectricCar будет удалено, а классы Автомобиль и ЭлектроАвтомобиль будут иметь свои реализации метода refuel().