Наблюдатель
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(); }
};