Шаблон наблюдателя - Как справиться с неожиданными изменениями? - PullRequest
0 голосов
/ 01 июля 2011

Какой механизм используется для обновления объекта ... если мы не постоянно проверяем, изменился ли он, а затем поручаем Субъекту / Наблюдаемому выдвинуть его состояние ...

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

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

Ответы [ 2 ]

2 голосов
/ 01 июля 2011

Существует множество различных механизмов для отслеживания изменений объекта.

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

class MyClass
   {
   public:
      void setValue(int value)
         {
         m_value = value;
         notifyObservers();
         }
   private:
      void notifyObservers()
         {
         for (auto it=m_observers.begin();it!=m_observers.end();++it)
            (*it)->notify(this);
         }
      std::list<Observer *> m_observers;
   };

Альтернативой является сохранение того, был ли объект изменен. Однако для этого необходимо определить значение слова «был изменен»; другими словами: когда я сбрасываю флаг «изменен». Простое решение - использовать номер версии. Всякий раз, когда объект изменяется, вы увеличиваете номер версии, например:

class MyClass
   {
   public:
      void setValue(int value)
         {
         m_value = value;
         ++m_version;
         }
      int getVersion() const
         {
         return m_version;
         }
   private:
      int m_version;
   };

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

Оба подхода имеют свои преимущества и недостатки:

  • В механизме наблюдателей изменения могут быть медленными (так как вам нужно вызвать всех наблюдателей), но вы гарантированно, что все наблюдатели будут немедленно обновлены
  • В подходе с номером версии изменения происходят очень быстро, но вы полагаетесь на другие классы, чтобы регулярно запрашивать изменения у вашего класса

Какой механизм является лучшим в вашем случае, зависит от ситуации. Если обнаружится, что на практике их лучше смешивать, в зависимости от ситуации. Некоторые изменения лучше всего распространять немедленно (например, в расчетах), другие изменения лучше всего откладывать (например, обновление экрана).

1 голос
/ 01 июля 2011

В основном шаблон Observer говорит, что существует объект, который представляет интерес для других объектов.
Скажем, например, у нас есть Kid объект, который имеет такие свойства, как MathGrade, GeographyGrade и т. Д.
Теперь все объекты Mother, Father, Principal заинтересованы в изменениях свойств объекта Kid.
У них есть в основном 2 варианта -

  1. подходит к Kid каждый день и спрашивает "изменился ли ваш MathGrade?" 'Ваш GeographyGrade изменился? и т.д.
    такой подход не очень эффективен.

  2. они могут просто сказать Kid - «Хорошо, вот мой номер - позвоните мне, если ваш MathGrade изменится».
    по сути, это паттерн Observer: тот, кто заинтересован в изменениях объекта, регистрируется в этом объекте и гарантированно получит уведомление при каждом изменении.

А если вернуться в мир программирования - у вас будет интерфейс IGradeObserver, который будет объявлять функции MathGradeChanged(int newGrade), GeorgraphyGradeChanged(int newGrade).
Классы Mother, Father и Principal будут реализовывать IGradeObserver.
Теперь класс Kid будет иметь список IGradeObservers и метод RegisterObserver(IGradeObserver observer).

Теперь, когда изменяется класс, класс Kid будет перебирать свой список наблюдателей и уведомлять их об этом изменении.

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

...