Шаблон Observer в Delphi расширяет базовый шаблон Observer. Дополнительную информацию о режиме наблюдателя см. в [Gam+, стр. 293..303].
Определите связь зависимости «один ко многим» между объектами. При изменении состояния объекта все зависящие от него объекты получают уведомление и автоматически обновляются.
Разделение системы на ряд взаимодействующих классов имеет определенные побочные эффекты: необходимо защищать согласованность между связанными объектами. Мы не хотим тесно связывать типы ради согласованности размеров, поскольку это снижает возможность их повторного использования. [Гам+, стр. 293].
События Delphi (фактические адреса методов) позволяют вам иметь хорошую структуру для решения этих проблем. События позволяют устранить связь и добиться лучшей связи. Например: событие TButton.OnClick отправляется для завершения связанной работы. Но класс не сохраняет ссылку на обработчик событий. В шаблоне наблюдателя класс, отправляющий событие, называется целевым объектом (субъектом), а класс, управляющий событием, называется наблюдателем (наблюдателем).
События в Delphi могут лучше устранить связь классов. Если вы хотите управлять несколькими событиями и использовать режим наблюдателя, вы можете установить механизм уведомления «один ко многим». Цель может иметь любое количество наблюдателей. Все наблюдатели получают уведомления при изменении состояния цели. После того как наблюдатель получает уведомление, он немедленно запрашивает целевой объект для поддержания синхронизации с целевым объектом.
Это взаимодействие также называется публикацией-подпиской, а целью является издатель уведомления. Ему не обязательно знать, кто является его наблюдателем, когда он обнаруживает уведомление. Любое количество наблюдателей может подписаться и получать уведомления.
Это приложение в режиме наблюдателя предоставит вам преимущества механизма событий Delphi при обработке связи классов. Структуры «один ко многим» регистрируют наблюдателей посредством регистрации и отмены регистрации. Механизм «один ко многим» фактически применяется на основе итераторов.
Предположим, у вас есть класс Tsubject, определяющий значимое поведение. Давайте сначала посмотрим на демонстрационный код режима наблюдателя:
тип
ТСубъект = класс (ТОбъект)
Частный
FОбсерверы: TList;
общественный
процедура RegisterObserver (Наблюдатель: TSubjectObserver);
процедура UnregisterObserver (Наблюдатель: TSubjectObserver);
конец;
TSubjectObserver = класс (TComponent)
частный
FВключено: логическое значение;
опубликовано
свойство Enabled: логическое чтение FEnabled запись FEnabled по умолчанию True;
конец;
Среди вышеперечисленных интерфейсов:
? Механизм регистрации наблюдателей для Tsubject.
¨ Fobservers: TList хранит зарегистрированных наблюдателей.
¨ RegisterObserver(..) используется для регистрации наблюдателей и добавления их на Fobservers.
¨ UnregisterObserver(..) используется для отмены регистрации наблюдателя и удаления связанных объектов с Fobservers.
?В режиме наблюдателя также необходимо создать новый класс TsubjectObserver.
¨ Этот класс является потомком TcomComponent.
¨ .Свойство Enabled включает или выключает наблюдение. .
Фактическое применение следующего режима наблюдателя:
процедура TSubject.RegisterObserver(Observer: TSubjectObserver);
начинать
если FOBservers.IndexOf(Observer) = -1, то
FObservers.Добавить(Наблюдатель);
конец;
процедура TSubject.UnregisterObserver(Observer: TSubjectObserver);
начинать
FObservers.Remove(Наблюдатель);
конец;
Реализация Shangguan поддерживает регистрацию наблюдателей. Где механизм уведомления «один ко многим»? Для реальных приложений уведомлений «один ко многим» вы можете определить метод Change для Tsubject, чтобы уведомлять своих зарегистрированных наблюдателей, а наблюдатель может определить атрибут события OnChange для управления планированием. Код выглядит следующим образом:
тип
ТСубъект = класс (ТОбъект)
частный
FОбсерверы: TList;
защищенный
» процедура Change {Вызовите этот метод для отправки уведомления};
общественный
процедура RegisterObserver (Наблюдатель: TSubjectObserver);
процедура UnregisterObserver (Наблюдатель: TSubjectObserver);
конец;
TSubjectObserver = класс (TComponent)
частный
FВключено: логическое значение;
» FOnChange: TNotifyEvent;
защищенный
» Изменение процедуры;
опубликовано
свойство Enabled: логическое чтение FEnabled запись FEnabled;
» свойство OnChange: TNotifyEvent чтение FOnChange запись FOnChange;
конец;
выполнение
процедураTSubject.Change;
вар
» Обс: TSubjectObserver;
» I: Целое число;
начинать
» for I := 0 to Fobservers.Count - 1 do
" начинать
» Obs := Fobservers[I];
» если Obs.Enabled, то Obs.Change;
" конец;
конец;
процедура TSubject.RegisterObserver(Observer: TSubjectObserver);
начинать
если FOBservers.IndexOf(Observer) = -1, то
FObservers.Добавить(Наблюдатель);
конец;
процедура TSubject.UnregisterObserver(Observer: TSubjectObserver);
начинать
FObservers.Remove(Наблюдатель);
конец;
процедураTSubjectObserver.Изменить;
начинать
» если Assigned(FOnChange), то FOnChange(Self);
конец;
В приведенном выше коде реализации:
? Метод Change объекта Tsubject перебирает всех зарегистрированных наблюдателей и вызывает метод Change каждого наблюдателя, реализацию уведомления «один ко многим».
? Свойство Enabled наблюдателя определяет, получает ли он уведомления.
? Событие OnChange TsubjectObserver фактически обрабатывает синхронизацию и другие операции.
Организация
//Многие выдержки из «Шаблонов проектирования»