lecture7

advertisement
1
Извлечение метода
Суть шаблона: группировка объединенного по смыслу кода в метод.
void printOwing (double amount) {
printBanner();
//printing details
System.out.println(“name:”+_name);
System.out.println(“Owing:”+ amount);
}
void printOwing (double amount) {
printBanner();
printDetails(amount);
}
void printDetails (double amount) {
System.out.println(“name:”+_name);
System.out.println(“Owing:”+ amount);
}
Преимущества применения данного паттерна:
 Извлечение метода увеличивает шансы других методов на повторное
использование кода, который содержится в извлеченном методе;
 Упрощается чтение вышестоящего метода
 Переопределение методов становится проще, когда методы хорошо разделены
Существенным является выбор удачного имени для извлекаемого метода; в противном
случае извлечение метода не принесет существенной пользы. При извлечении метода
важно обратить внимание не только на длину исходного метода, но и на семантическую
связанность отдельных строк и фрагментов кода в нем.
Процедура








Определите новый метод и дайте ему имя в соответствии с его назначением (имя
должно отражать то, что делает метод, а не то, как он это делает)
Скопируйте извлекаемый код в новый метод
Просмотрите извлекаемый код на предмет наличия ссылок на переменные, которые
являются локальными в исходном методе. Это могут быть также параметры
исходного метода
Определите, нет ли переменных в исходном методе, которые используются в
извлекаемом коде только для чтения. Если есть, скопируйте их в целевой метод в
качестве параметров
Определите, есть ли в исходном методе локальные переменные или параметры,
значения которых изменяются в извлекаемом коде. Если такая переменная одна,
попытайтесь сделать ее возвращаемым параметров извлекаемого метода (метод
будет работать как функция, возвращающая значение данной переменной). Если же
таких переменных больше, или же функцию неудобно использовать как запрос, то
извлечь метод сходу невозможно. Необходимо вначале использовать другие
подходы для устранения «лишних» локальных переменных
Передайте в целевой метод необходимые локальные переменные в качестве
параметров
Замените извлекаемый код в исходном методе на вызов целевого метода
Откомпилируйте и протестируйте измененный класс
Пример
2
void printOwing (double amount) {
Enumerator e = _orders.elements();
double outstanding = 0.0;
void printOwing (double amount) {
printBanner();
double outstanding = getOutstanding();
printDetails(outstanding);
printBanner();
double getOutstanding() {
Enumerator e = _orders.elements();
double outstanding = 0.0;
while (e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
return outstanding;
//calculate outstanding
while (e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
}
}
Метод в строке
Суть шаблона противоположна рассмотренному ранее. Метод удаляется, а его код
переносится в вызывающий метод.
int getRating {
return (moreThanFiveLateDeliveries())?2:1;
}
boolean moreThanFiveLateDeliveries() {
return _numberOfLateDeliveries>5;
}
int getRating {
return (_numberOfLateDeliveries>5)?2:1;
}
Метод применим в том случае, когда реализация кода является столь же очевидной, как и
имя метода, т.е. наличие метода не добавляет ничего для понимания кода и не облегчает
это понимание, а наоборот, загромождает код.
Еще один возможный случай для использования данного шаблона: наличие большой
группы мелких методов, которые были неудачно определены на этапе проектирования.
Т.е. есть возможность все эти методы объединить в один большой и затем разбить его на
несколько мелких, повысив качество разбиения. Также данный шаблон может
использоваться для устранения избыточного делегирования методами какого-то класса.
Процедура





Убедитесь, что метод не переопределяется в классах-потомках
Найдите все вызовы метода
Замените каждый из вызовов телом метода
Откомпилируйте и протестируйте проект
Уддалите определение метода
Шаблон только выглядит довольно простым. В действительности, он подразумевает
множество подводных камней: рекурсии, множественные точки выхода и другие.
3
Замена переменной на запрос
Суть шаблона: имеется переменная, которая хранит результат вычисления. Это
вычисление переносится в метод, который может быть использован в других методах.
double basePrice = _quantity * _itemPrice;
if (basePrice>1000)
return basePrice*0.5
else
return basePrice*0.8;
if (basePrice()>1000)
return basePrice*0.5
else
return basePrice*0.8;
…
double basePrice() {
return _quantity * _itemPrice;
}
Смысл преобразония состоит в избавлении от локальных переменных. Такие переменные
видны только в пределах метода, где определены, и поэтому имеется тенденция к
увеличению размеров этого метода. При удалении временных переменных и создании
методов-запросов любой метод класса может получить доступ к рассчитываемым данным.
Процедура





Найдите локальную переменную, которая получает значение всего один раз
Обїявите ее как final и откомпилируйте код
Извлеките правую часть выражения присваивания в метод. При этом необходимо
убедиться, что данный метод не модифицирует никаких объектов.
Откомпилируйте код
Удалите переменную и ее объявление, замените использование переменной
вызовом метода.
Переменная в строке
Суть шаблона: отказ от использования локальных переменных, которые используются
лишь для хранения значения вызываемых функций.
double basePrice = anOrder.basePrice();
return (basePrice>1000);
return (anOrder.basePrice()>1000);
Как правило, данный шаблон используется вместе с шаблоном Замена переменной на
запрос. Но он может использоваться и самостоятельно, если существует переменная,
принимающая значение вызываемой функции. Если эта переменная мешает применению
других шаблонов (например, извлечение метода), то ее можно удалить с помощью
данного шаблона.
Процедура





Объявите переменную как final и скомпилируйте код (это нужно для того, чтобы
проверить, что переменная инициализируется всего один раз)
Найдите все ссылки на переменную и замените их на правую часть
соответствующей операции присваивания
Компилируйте код после каждой замены
Удалите объявление и присваивание переменной
Откомпилируйте код
Download