Казахстан, Караганды, Карагандинский экономический университет, 2009 |
Поведенческие шаблоны проектирования
Наблюдатель
В том случае, когда информационная система состоит из множества различных классов и взаимодействующих объектов, которые находятся в согласованных состояниях между собой, когда необходимо сохранять гибкость системы или избегать монолитности путем повышения возможности переиспользования существующих классов, принято использовать шаблон проектирования "Наблюдатель".
Если попробовать описать суть данного паттерна в виде метафоры, то наиболее удачным является сравнение с приходящей к вам рассылкой. В этом случае устройство, на которое вы получаете рассылку (телефон, компьютер и пр.), реализует шаблон "Наблюдатель". То есть:
- один объект ("Подписчик") должен знать об изменении состояний или некоторых специализированных событиях другого объекта;
- при этом необходимо поддерживать низкий уровень связывания с самим объектом –"Подписчиком".
Таким образом, этот шаблон определяет зависимость "один-ко-многим" между объектами так, что при изменении состояния одного объекта все зависящие от него объекты уведомляются и обновляются автоматически.
Объект представляет основную, достаточно независимую абстракцию, "наблюдатель" является зависимой абстракцией. Объект извещает наблюдателей о своем изменении, на что каждый наблюдатель будет реагировать по-своему, может запросить дополнительную информацию от объекта, а может проигнорировать изменившееся состояние.
Шаблон "Наблюдатель" можно охарактеризовать следующими отличительными чертами:
- Шаблон "Наблюдатель" скрывает главный компонент в объект-абстракцию, а изменяемые компоненты в иерархию наблюдателей.
- "Наблюдатель" определяет часть представление в рассмотренном ранее архитектурном шаблонеModel-View-Controller (MVC).
- Он находит широкое применение в системах пользовательского интерфейса, в которых данные и их представления ("виды") отделены друг от друга:
- При изменении данных должны быть изменены все представления этих данных (например, в виде таблицы, графика и диаграммы).
Для реализации шаблона наблюдатель необходимо:
- Определить интерфейс "Подписки". Это интерфейс должен быть спроектирован оптимальным образом, не слишком большим, но и не слишком специализированным:
- Если сделать его слишком большим, то есть включающим большое количество данных, то это приведет к потере целостности шаблона. Он рискует постепенно мутировать к виду шаблона "Репозиторий", назначение которого противоречит назначению шаблона "Наблюдатель".
- Слишком специализированный интерфейс приведет к дублированию шаблонов, передающих сходную информацию.
- Метрикой оптимальности состава интерфейса этого шаблона является его ограниченность объектом предметной области, реализованной в конкретной информационной системе.
- Объекты-подписчики реализуют этот интерфейс и динамически регистрируются для получения информации о некотором событии, которое является триггером для их обновления.
- При реализации условленного события оповещаются все объекты-подписчики.
В качестве основных достоинств применения шаблона "Наблюдатель" являются:
- Минимальная связанность объекта и наблюдателя.
- Объект знает лишь о том, что у него есть ряд наблюдателей.
- Широковещательность оповещения.
- Объект оповещает не конкретного, а всех подписанных на него наблюдателей.
Недостатками являются:
- Непредвиденные обновления.
- Изменение объекта может вызвать каскад зависимых от него наблюдателей с высокой стоимостью обновления.
- Протокол обновления не содержит никаких сведений о том, что изменилось в субъекте,– работа наблюдателей при этом усложняется.
Не разговаривайте с неизвестным
"Не разговаривайте с неизвестным" – один из самых неизвестных шаблонов проектирования, задача которого состоит в снижении монолитности и повышении гибкости системы за счет снижения зависимости объекта от косвенных компонентов системы, о которых ему напрямую ничего не известно.
При его реализации следует избегать решений, предполагающих взаимодействие с удаленными непрямыми объектами ("незнакомцами"). Во многом этот шаблон воспринимается как частный случай уже рассмотренного нами ранее паттерна "Устойчивый к изменениям".
Что касается явных недостатков применения этого шаблона, стоит отметить, что прямым объектам потребуются новые операции, поддерживающие реализацию данного шаблона.
В конечном итоге, использование шаблона "Не разговаривайте с неизвестным" позволит обеспечить устойчивость системы к изменению структуры отдельных объектов.
Посетитель
Применение шаблона "Посетитель" оправданно в ситуациях, когда над объектом конкретной структуры необходимо определить новую операцию, но при этом не требуется изменять исходный класс.
Компонент, использующий данный паттерн:
- должен создать объект класса ("Конкретный посетитель");
- "посетить" каждый элемент структуры:
- Посетитель объявляет операцию "Посетить" для каждого "Конкретного элемента". Имя и сигнатура данной операции идентифицируют класс, элемент которого посещает "Посетитель".То есть "Посетитель" может обращаться к элементу напрямую.
- "Конкретный посетитель" реализует все операции, объявленные в классе "Посетитель".
- Каждая операция реализует фрагмент алгоритма, определенного для класса соответствующего объекта в структуре.
- "Конкретный посетитель" предоставляет контекст для этого алгоритма и сохраняет его локальное состояние.
- "Элемент" определяет операцию "Принять", которая принимает "Посетителя" в качестве аргумента.
- "Конкретный элемент" реализует операцию "Принять", которая принимает "Посетителя" в качестве аргумента.
- Структура объекта может перечислить свои аргументы и предоставить "Посетителю" высокоуровневый интерфейс для посещения своих элементов.
Исходя из описания реализации шаблона "Посетитель", обоснованно предположить, что его логично использовать, если в структуре присутствуют объекты многих классов с различными интерфейсами, и необходимо выполнить над ними операции, зависящие от конкретных классов, или если классы, устанавливающие структуру объектов, изменяются редко, но новые операции над этой структурой добавляются часто.
Главными преимуществами применения этого паттерна являются следующие:
- Упрощается добавление новых операций к существующим в системе объектам.
- Он объединяет родственные операции в едином классе.
При этом в качестве основного недостатка выделим то, что затруднено добавление новых классов к системным "элементам", поскольку требуется объявление новой абстрактной операции в классе "Посетитель".
В качестве аналогии этого шаблона можно выделить работника, приходящего на определенное время для выполнения узкоспециализированных операций (няня, уборщица и т.д.). Работник приходит для выполнения конкретных действий, выполнение которых отвлекает хозяев от их обыденной жизни, и уходит, получив конкретное возмещение за проделанный труд. Конечно, можно переложить на него и дополнительные обязанности, но это потребует от хозяев вложения дополнительных средств.