Книга: Экстремальное программирование. Разработка через тестирование

Встраиваемый объект (Pluggable Object)

Встраиваемый объект (Pluggable Object)

Как можно выразить несколько разных вариантов поведения кода? Проще всего использовать явный условный оператор:

if(circle) then {

… код, относящийся к circle.

} else {

… код, не относящийся к circle

}

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

Вторая по важности задача TDD – устранение дублирования, поэтому вы должны подавить угрозу распространения явных условных операторов в зародыше. Если вы видите, что одно и то же условие проверяется в двух разных местах вашего кода, значит, настало время выполнить базовое объектно-ориентированное преобразование: «Встраиваемый объект» (PluggableObject).

Иногда обнаружить необходимость применения этого шаблона не так просто. Один из самых любимых мною примеров использования встраиваемого объекта был придуман мною и Эрихом Гаммой. Представьте, что мы занимаемся разработкой графического редактора. Если вы когда-нибудь занимались чем-либо подобным, должно быть, вы знаете, что операция выделения объектов обладает несколько усложненной логикой. Если указатель мыши находится над графической фигурой и пользователь нажимает кнопку мыши, значит, последующие перемещения мыши приводят к перемещению фигуры, а при отпускании кнопки мыши выбранная фигура остается на новом месте. Если указатель мыши не находится над какой-либо фигурой, значит, нажав кнопку, пользователь выделяет несколько фигур, последующие перемещения мыши приводят к изменению размера прямоугольника выделения, а при отпускании кнопки мыши фигуры внутри прямоугольника выделения становятся выделенными. Изначальный код выглядит примерно так:

SelectionTool

Figure selected;

public void mouseDown() {

selected = findFigure();

if (selected!= null)

select(selected);

}

public void mouseMove() {

if (selected!= null)

move(selected);

else

moveSelectionRectangle();

}

public void mouseUp() {

if (selected == null)

selectAll();

}

В глаза бросаются три похожих условных оператора (я же говорил, что они плодятся, как мухи). Что делать, чтобы избавиться от них? Создаем встраиваемый объект, SelectionMode, обладающий двумя реализациями: SingleSelection и MultipleSelection.

SelectionTool

SelectionMode mode;

public void mouseDown() {

selected = findFigure();

if (selected!= null)

mode = SingleSelection(selected);

else

mode = MultipleSelection();

}

public void mouseMove() {

mode.mouseMove();

}

public void mouseUp() {

mode.mouseUp();

}

В языках с явными интерфейсами вы обязаны реализовать интерфейс с двумя (или больше) встраиваемыми объектами.

Оглавление книги


Генерация: 1.168. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз