Опубликован: 18.09.2006 | Уровень: специалист | Доступ: свободно | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 8:

Образцы проектирования (продолжение)

< Лекция 7 || Лекция 8: 12345 || Лекция 9 >

Идиомы

Идиома представляет собой типовое решение, определяющее специфическую структуризацию элементов кода на некотором языке программирования. Чаще всего это некоторый "трюк", с помощью которого можно придать программе на данном языке нужные свойства. При этом идиома может оказаться специфичной для языка и не иметь аналога в других языках. Кроме того, очень часто удачные идиомы при развитии языков программирования превращаются в новые синтаксические конструкции, делающие такую идиому ненужной.

Далее мы увидим примеры таких идиом в виде соглашений о построении кода компонентов JavaBeans, превратившихся в C# в элементы языка.

В этой лекции мы рассмотрим в качестве примера идиому "шаблонный метод" [3].

Шаблонный метод

Название. Шаблонный метод (template method).

Назначение. Фиксация общей схемы некоторого алгоритма, имеющего много вариантов, с предоставлением возможности реализовать эти варианты за счет переопределения отдельных его шагов, без изменения схемы в целом. При использовании этой идиомы нужно принимать во внимание следующие факторы:

Действующие силы.

  • Инвариантные части алгоритма нужно записать один раз и переиспользовать, изменяя только варьирующиеся шаги и элементы.
  • Иногда такие инвариантные части еще нужно выделить, чтобы сделать более понятным и более удобным для сопровождения код нескольких классов, реализующих близкие по назначению методы.
  • Многие алгоритмы при их практическом использовании могут зависеть от большого числа факторов, изменяющихся гораздо чаще, чем общая схема такого алгоритма (вспомните принцип разделения политик и алгоритмов).

Решение. Общая схема алгоритма, которую нужно зафиксировать, помещается в абстрактный класс в виде метода, код которого реализует эту схему. В тех местах, где необходимо использовать какой-то варьирующийся элемент алгоритма, этот метод обращается к другому методу данного класса, который можно переопределить в классах-потомках.

Структура. Метод, реализующий основную схему алгоритма, называется шаблонным методом. Он пишется один раз в абстрактном базовом классе и не переопределяется в потомках. Методы, вызываемые им, делятся на следующие группы:

  • Конкретные операции, реализация которых известна на момент написания метода и не должна изменяться.
  • Абстрактные операции, которые представляют собой изменяемые части алгоритма. Они не имеют реализации и должны определяться в каждом классе-потомке в соответствии с теми вариациями, которые он вносит в базовый алгоритм.
  • Операции-перехватчики, или зацепки (hook operations), которые также представляют собой изменяемые элементы алгоритма, но имеют некоторую реализацию по умолчанию, записанную в базовом классе. Эти операции могут переопределяться в классах-потомках, если представляемые ими элементы алгоритма нужно изменить по сравнению с имеющейся реализацией по умолчанию.
  • Фабричные методы (factory methods), предназначенные для создания объектов, которые связаны с работой конкретного варианта алгоритма. Они реализуются по образцу, также называемому "фабричный метод". Суть такого метода в том, что при его вызове мы точно не знаем, объект какого конкретного класса будет создан — это зависит от текущей конфигурации системы.

Динамика. Типичный сценарий работы шаблонного метода показан на рис. 8.6. Для наглядности на этой диаграмме операции, выполняемые в одном объекте, разделены между двумя виртуальными объектами: первый представляет все действия, выполняемые в рамках абстрактного класса, определяющего шаблонный метод, а второй — те действия, которые (пере)определяются в конкретном подклассе.

Сценарий работы шаблонного метода

увеличить изображение
Рис. 8.6. Сценарий работы шаблонного метода

Реализация. Основные шаги реализации следующие:

  • Определить основные шаги алгоритма. Определить набор данных, которыми он пользуется.
  • Выделить среди шагов алгоритма те, которые зависят от конкретных политик. Определить для каждого такого шага абстрактный метод.
  • Выделить среди данных, которыми пользуется алгоритм, те, чья структура зависит от политик или конкретного варианта алгоритма. Определить для порождения таких данных фабричные методы, а для операций над ними — абстрактные методы. Для их представления могут понадобиться дополнительные классы, но изменяемая часть данных должна, по возможности, находиться в абстрактном классе, определяющем шаблонный метод.
  • Реализовать общую схему алгоритма в теле шаблонного метода. Выделить его элементы, используемые несколько раз или представляющие собой отдельные операции, в отдельные методы абстрактного класса.
  • Определить, какие дополнительные возможности по вариации поведения алгоритма могут понадобиться. Определить для таких возможностей методы-перехватчики.
  • Определить несколько наиболее часто используемых вариантов алгоритма. Реализовать их в виде подклассов определяющего шаблонный метод класса, определив в них методы, которые представляют абстрактные операции, и, если это необходимо, переопределив методы-перехватчики.

Следствия применения образца.

Достоинства:

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

Недостатки:

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

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

Жизненный цикл компонентов EJB реализован в виде шаблонного метода, в котором абстрактной операцией служит создание объектов данного компонента. Имеется также несколько операций-перехватчиков, позволяющих разработчику компонента специфическим образом обрабатывать переход компонента из одного состояния в другое.

Другой пример — реализация метода start(), запускающего отдельный поток в Java. Инструкции, выполняемые в рамках потока, помещаются в метод run() объекта класса Thread или класса, реализующего интерфейс Runnable. Этот метод служит операцией-перехватчиком для метода start() — реализация метода run() по умолчанию ничего не делает.

< Лекция 7 || Лекция 8: 12345 || Лекция 9 >
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!

Лариса Парфенова
Лариса Парфенова

1) Можно ли экстерном получить второе высшее образование "Программная инженерия" ?

2) Трудоустраиваете ли Вы выпускников?

3) Можно ли с Вашим дипломом поступить в аспирантуру?