Замена наследования делегированием.
У вас есть подкласс, который использует только часть методов суперкласса или не хочет наследовать его данные.
Создайте поле и поместите в него объект суперкласса, делегируйте выполнение методов объекту-суперклассу, уберите наследование.
##Пример
class Stack extends Vector {
void push(Object element) {
insertElementAt(element, 0);
}
Object pop() {
Object result = firstElement();
removeElementAt(0);
return result;
}
}class Stack {
private Vector elements = new Vector();
void push(Object element) {
elements.insertElementAt(element, 0);
}
Object pop() {
Object result = elements.firstElement();
elements.removeElementAt(0);
return result;
}
boolean isEmpty() {
return elements.isEmpty();
}
}##Зачем делать рефакторинг
Замена наследования композицией может значительно улучшить дизайн классов, если:
-
Ваш подкласс нарушает принцип замещения Барбары Лисков. Другими словами, наследование возникло только ради объединения общего кода, но не потому, что подкласс «является» (is-a) расширением суперкласса.
-
Подкласс использует только часть методов суперкласса. В этом случае, это только вопрос времени, пока кто-то не вызовет метод суперкласса, который он не должен был вызывать.
Суть рефакторинга сводится к тому, чтобы разделить оба класса, и сделать суперкласс помощником подкласса, а не его родителем. Вместо того чтобы наследовать все методы суперкласса, подкласс будет иметь только необходимые методы, которые будут делегировать выполнение методам объекта-суперкласса.
##Преимущества
-
Класс не содержит лишних методов, которые достались ему в наследство от суперкласса.
-
В поле-делегат можно подставлять разные объекты, имеющие различные реализации функциональности. По сути, вы получаете реализацию паттерна проектирования Стратегия.
##Как делать рефакторинг
-
Создайте поле в подклассе для содержания суперкласса. На первом этапе поместите в него текущий объект.
-
Измените методы подкласса так, чтобы они использовали объект суперкласса, вместо
this. -
Для методов, которые были унаследованы из суперкласса и которые вызываются в клиентском коде, в подклассе нужно создать простые делегирующие методы.
-
Уберите объявление наследования из подкласса.
-
Измените код инициализации поля, в котором хранится бывший суперкласс, созданием нового объекта.