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

Создание шаблонного метода.

Проблема

В подклассах реализованы алгоритмы, содержащие похожие шаги и одинаковый порядок выполнения этих шагов.

Решение

Вынесите структуру алгоритма и одинаковые шаги в суперкласс, а в подклассах оставьте реализацию отличающихся шагов.

##Пример

До
class ResidentialSite extends Site {
  double getBillableAmount() {
    double baseAmount = units * rate;
    double tax = baseAmount * Site.TAX_RATE;
    return baseAmount + tax;
  }
}
class LifelineSite extends Site {
  double getBillableAmount() {
    double baseAmount = units * rate * 0.5;
    double tax = baseAmount * Site.TAX_RATE;
    return baseAmount + tax;
  }
}
После
abstract class Site {
  double getBillableAmount() {
    return getBaseAmount() + getTaxAmount();
  }
  double getTaxAmount() {
    return getBaseAmount() * TAX_RATE;
  }
  abstract double getBaseAmount();
}
class ResidentialSite extends Site {
  double getBaseAmount() { return units * rate; }
}
class LifelineSite extends Site {
  double getBaseAmount() { return units * rate * 0.5; }
}

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

Подклассы развиваются параллельно. Иногда разными людьми, что приводит к дублированию кода и ошибок, а также к усложнению поддержки, так как каждое изменение приходится проводить во всех подклассах.

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

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

  • Создание шаблонного метода реализует принцип открытости/закрытости. При появлении новой версии алгоритма, вам нужно будет всего лишь создать новый подкласс, не меняя существующий код.

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

  1. Разбейте алгоритмы в подклассах на составные части, описанные в отдельных методах. В этом может помочь извлечение метода.

  2. Получившиеся методы, одинаковые для всех подклассов, можете смело перемещать в суперкласс, используя подъём метода.

  3. Отличающиеся методы приведите к единым названиям с помощью переименования метода.

  4. Поместите сигнатуры отличающихся методов в суперкласс как абстрактные с помощью подъёма метода. Их реализации оставьте в подклассах.

  5. И наконец, поднимите основной метод алгоритма в суперкласс. Он теперь должен работать с методами-шагами, описанными в суперклассе — реальными или абстрактными.