printПаттерны поведения

printНаблюдатель

Observer

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

Результаты
1. Субъект имеет информацию лишь о том, что у него есть ряд наблюдателей, каждый из которых подчиняется простому интерфейсу абстрактного класса Observer. Субъекту неизвестны конкретные классы наблюдателей. Таким образом, связи между субъектами и наблюдателями носят абстрактный характер и сведены к минимуму. Это дает возможность добавлять новые виды наблюдателей без модификации субъекта или других наблюдателей.
2. Для уведомления, посылаемого субъектом, не нужно задавать определенного получателя. Уведомление автоматически поступает всем подписавшимся на него объектам. Субъекту не нужна информация о количестве таких объектов, от него требуется всего лишь уведомить своих наблюдателей. Поэтому мы можем в любое время добавлять и удалять наблюдателей. Наблюдатель сам решает, обработать полученное уведомление или игнорировать его.
3. Поскольку наблюдатели не располагают информацией друг о друге, им неизвестно и о том, во что обходится изменение субъекта. Простая операция над субъектом может вызвать каскад обновлений наблюдателей и зависящих от них объектов. Если протокол обновления не содержит никаких сведений о том, что именно изменилось в субъекте, то наблюдатели будут вынуждены проделать сложную работу для косвенного получения такой информации.

Реализация
// Наблюдатель определяет интерфейс уведомления
class Observer {
public:
  virtual void Update() {}
};
// Субъект предоставляет интерфейс для работы с наблюдателями
class Subject {
  vector <Observer *> obs;
public:
  void Attach(Observer *o) 
  { obs.push_back(o); 
  }
  void Detach(Observer *o) 
  { obs.erase(find(obs.begin(),obs.end(),o)); 
  }
  void Notify()
  { for(size_t i=0; i<obs.size(); ++i)
      obs[i]->Update();
  } 
};
// Конкретный субъект хранит состояние, представляющее интерес для наблюдателей
class Subject1 : public Subject {
  int state;
public:
  int GetState() const { return state; }
  void SetState(int s) 
  { if(s!=state) 
    { state=s;
      Notify();
    }
  }
};
// Конкретный наблюдатель хранит данные, которые должны быть согласованы с данными субъекта
class Observer1 : public Observer {
  Subject1 *s;
  int state;
public:
  Observer(Subject1 *s):s(s) { s->Attach(this); }
  ~Observer() { s->Detach(this); }
  void Update() { state=s->GetState(); }
};
loading