lecture9

advertisement
1
Перемещение атрибута
Вообще, процесс перемещения методов и атрибутов между классами является одним из
основных при проведении рефакторинга.
По аналогии с перемещением метода, перемещение атрибута происходит тогда, когда
атрибут является более востребованным методами другого класса, чем своего.
Использование атрибута может быть непрямым, а скажем через getting/setting – методы.
Процедура








Если атрибут объявлен как public, его нужно инкапсулировать (т.е. объявить
как private, создать getting/setting методы, заменить все обращения к
атрибуту)
Откомпилировать и протестировать код
Создать атрибут в целевом классе, а также getting/setting методы для него
Откомпилировать и протестировать код
Определить, как именно можно сослаться на целевой объект из исходного.
Например, это может быть существующие атрибут или метод. Если же нет,
рассмотрите возможность быстрого создания метода, который бы решал
такую задачу. Если же и это невозможно, необходимо создать атрибут в
целевом классе, который бы хранил ссылку на исходный класс. Это может
оказаться постоянной ссылкой, но может и временной, которая
впоследствии будет удалена на последующих стадиях рефакторинга
Удалить атрибут в исходном классе
Заменить все ссылки на исходный атрибут на ссылки на соответствующий
метод целевого атрибута. Если атрибут был не private, ссылки следует
поискать и во всех под-классах исходного класса.
Откомпилировать и протестировать
Пример.
Фрагмент класса Account
class Account…
{
private AccountType _type;
private double _interestRate;
double interestForAmount_days (double amount, int days) {
return _interestRate*amount*days/365;
}
}
Целесообразно переместить атрибут _interestRate в класс типа счета. Создаем атрибут и
getting/setting методы.
class AccountType…
private double _interestRate;
void set interestRate(double arg) {
_interestRate=arg;
}
2
double getInterestRate() {
return _interestRate;
}
Теперь нужно перенаправить методі от класса счета к классу типа счета. Затем
необходимо удалить атрибут _interestRate из класса счета.
private double _interestRate;
double interestForAmount_days (double amount, int days) {
return _type.interestRate*amount*days/365;
}
Пример с инкапсуляцией.
class Account…
{
private AccountType _type;
private double _interestRate;
double interestForAmount_days (double amount, int days) {
return getInterestRate()*amount*days/365;
}
private void setInterestRate(double arg) {
_interestRate=arg;
}
private double getInterestRate() {
return _interestRate;
}
}
Если атрибут инкапсулирован, то достаточно просто перенаправить аксессоры на целевой
класс:
private void setInterestRate(double arg) {
_type.setInterestRate(arg);
}
private double getInterestRate() {
return type.getInterestRate();
}
Извлечение класса
Прием состоит в разбиении класса на два. Используется в случаях, когда исходный класс
«перегружен» свойствами, и тяжело понять, что он означает и для чего нужен. Разбиение
легко сделать, когда подмножество атрибутов и методов выглядят «похоже», т.е. часто
используются вместе.
Процедура
3









Определите, каким образом следует разбить сферы ответственности исходного
класса
Создайте новый класс, который будет содержать извлекаемые свойства
Если свойства и ответственность старого класса уже не отражают корректно его
имя, переименуйте класс
Создайте связь между старым и новым классами. Может понадобиться
двусторонняя связь, однако ее не следуент создавать, пока вы не поймете, что она
действительно нужна
Используйте шаблон «перемещение атрибута» для каждого из атрибутов, который
нужно перенести
Откомпилируйте и протестируйте код после каждого переноса
Используйте шаблон «перемещение метода» для каждого из методов, который вы
хотите перенести
Откомпилируйте и протестируйте код после кажлого переноса
Просмотрите раздел объявлений каждого из классов, удалите все лишнее
Download