Ответ 1
Цитата прямо из в документе:
Чтобы проиллюстрировать точные проблемы шаблона наблюдателя,
мы начинаем с простого и повселокального примера: перетаскивание мышью.
Следующий пример отслеживает движения
мыши во время операции перетаскивания в объекте Path
и отображает
это на экране. Чтобы все было просто, мы используем Scala замыкания
как наблюдатели.
var path: Path = null
val moveObserver = { (event: MouseEvent) =>
path.lineTo(event.position)
draw(path)
}
control.addMouseDownObserver { event =>
path = new Path(event.position)
control.addMouseMoveObserver(moveObserver)
}
control.addMouseUpObserver { event =>
control.removeMouseMoveObserver(moveObserver)
path.close()
draw(path)
}
Приведенный выше пример, и, как мы будем утверждать, наблюдатель как определено в [25] в целом, нарушает впечатляющий состав важных принципов разработки программного обеспечения:
Побочные эффекты Наблюдатели способствуют побочным эффектам. Поскольку наблюдатели
являются лицами без гражданства, нам часто нужно несколько из них, чтобы имитировать
конечный автомат, как в примере перетаскивания. Мы должны сэкономить
государство, в котором оно доступно всем задействованным наблюдателям
например, в переменной Path
выше.
Инкапсуляция Поскольку переменная состояния Path
выходит из области действия
наблюдателей картина наблюдателя ломает инкапсуляцию.
Композиция Несколько наблюдателей образуют свободную коллекцию объектов, которые касаются одной проблемы (или нескольких, см. следующий пункт). Поскольку несколько наблюдателей установлены на разные точки в разное время, мы не можем, например, легко распоряжаться ими вообще.
Разделение проблем Вышеуказанные наблюдатели не только отслеживают путь мыши, но также вызов команды рисования или в более общем плане, включают две различные проблемы в такое же расположение кода. Часто предпочтительнее отделять проблемы построения пути и отображения его, например, как в шаблоне модели-просмотра (MVC) [30].
Scalablity. Мы могли бы добиться разделения проблем в нашей Например, создав класс для путей, который сам публикует события, когда путь изменяется. К сожалению, нет гарантируют согласованность данных в шаблоне наблюдателя. Предположим, мы создадим другое событие публикации объект, который зависит от изменений в нашем исходном пути, например, прямоугольник, представляющий границы нашего пути. Также рассмотреть наблюдателя, слушая изменения как в путь и его границы, чтобы нарисовать обрамленный путь. Эта наблюдателю необходимо вручную определить, границы уже обновлены, и если нет, отложите чертеж операция. В противном случае пользователь мог бы наблюдать экран с неправильным размером (сбой).
Однородность Различные способы установки разных наблюдателей уменьшить однородность кода.
Абстракция В примере представлен низкий уровень абстракции. Он полагается на супертяжелый интерфейс управления класс, который обеспечивает не только определенные методы установки наблюдателей событий мыши. Поэтому мы не можем абстрагироваться над точными источниками событий. Например, мы может позволить пользователю прервать операцию перетаскивания, нажав на escape или использовать другое устройство указателя, такое как касание экран или графический планшет.
Управление ресурсами Жизненный цикл наблюдателей должен быть управляемых клиентами. Из-за соображений производительности, мы хотим наблюдать за событиями перемещения мыши только во время перетащите. Поэтому нам необходимо явно установить и удалите наблюдателя перемещения мыши, и нам нужно вспомните точку установки (см. выше).
Семантическое расстояние В конечном счете, пример трудно понять потому что поток управления инвертирован, результаты в слишком большом шаблоне кода, который увеличивает семантическую расстояние между намерениями программистов и фактический код.
[25] Э. Гамма, Р. Хельм, Р. Джонсон и Дж. Влиссидес. дизайн шаблоны: элементы многоразового объектно-ориентированного программного обеспечения. Addison-Wesley Longman Publishing Co., Inc., Бостон, Массачусетс, USA, 1995. ISBN 0-201-63361-2.