Читайте также:
|
|
В этом разделе обсуждаются вопросы, относящиеся к реализации механизма зависимостей:
а отображение субъектов на наблюдателей. С помощью этого простейшего способа субъект может отследить всех наблюдателей, которым он должен посылать уведомления, то есть хранить на них явные ссылки. Однако при наличии большого числа субъектов и всего нескольких наблюдателей это может оказаться накладно. Один из возможных компромиссов в пользу экономии памяти за счет времени состоит в том, чтобы использовать ассоциативный массив (например, хэш-таблицу) для хранения отображения между субъектами и наблюдателями. Тогда субъект, у которого нет наблюдателей, не будет зря расходовать память. С другой стороны, при таком подходе увеличивается время поиска наблюдателей;
а наблюдение более чем за одним субъектом. Иногда наблюдатель может зависеть более чем от одного субъекта. Например, у электронной таблицы бывает более одного источника данных. В таких случаях необходимо расширить интерфейс Update, чтобы наблюдатель мог «узнать», какой субъект прислал уведомление. Субъект может просто передать себя в качестве параметра операции Update, тем самым сообщая наблюдателю, что именно нужно обследовать;
а кто инициирует обновление. Чтобы сохранить согласованность, субъект и его наблюдатели полагаются на механизм уведомлений. Но какой именно объект вызывает операцию-Notify для инициирования обновления? Есть два варианта:
Паттерн Observer
- операции класса Sub j ect, изменившие состояние, вызывают Noti f у для
уведомления об этом изменении. Преимущество такого подхода в том, что
клиентам не надо помнить о необходимости вызывать операцию Notify
субъекта. Недостаток же заключается в следующем: при выполнении каж
дой из нескольких последовательных операций будут производиться обнов
ления, что может стать причиной неэффективной работы программы;
- ответственность за своевременный вызов Notify возлагается на клиен
та. Преимущество: клиент может отложить инициирование обновления
до завершения серии изменений, исключив тем самым ненужные проме
жуточные обновления. Недостаток: у клиентов появляется дополнитель
ная обязанность. Это увеличивает вероятность ошибок, поскольку кли
ент может забыть вызвать Notify;
а висячие ссылки на удаленные субъекты. Удаление субъекта не должно приводить к появлению висячих ссылок у наблюдателей. Избежать этого можно, например, поручив субъекту уведомлять все свои наблюдатели о своем удалении, чтобы они могли уничтожить хранимые у себя ссылки. В общем случае простое удаление наблюдателей не годится, так как на них могут ссылаться другие объекты и под их наблюдением могут находиться другие субъекты;
а гарантии непротиворечивости состояния субъекта перед отправкой уведомления. Важно быть уверенным, что перед вызовом операции Notify состояние субъекта непротиворечиво, поскольку в процессе обновления собственного состояния наблюдатели будут опрашивать состояние субъекта. Правило непротиворечивости очень легко нарушить, если операции одного из подклассов класса Subject вызывают унаследованные операции. Например, в следующем фрагменте уведомление отправляется, когда состояние субъекта противоречиво:
void MySubject::0peration (int newValue) { В aseClass Subject::Operation(newValue); // отправить уведомление
_my!nstVar += newValue;
// обновить состояние подкласса (слишком поздно!) }
Избежать этой ловушки можно, отправляя уведомления из шаблонных методов (см. описание паттерна шаблонный метод) абстрактного класса Subject. Определите примитивную операцию, замещаемую в подклассах, и обратитесь к Notify, используя последнюю операцию в шаблонном методе. В таком случае существует гарантия, что состояние объекта непротиворечиво, если операции Subject замещены в подклассах:
void Text::Cut (TextRange r) {
ReplaceRange(г); // переопределена в подклассах Notify ();
Дата добавления: 2015-09-11; просмотров: 75 | Поможем написать вашу работу | Нарушение авторских прав |