///
// Observer pattern
// - Define a one-to-many dependency between objects so that when one object
// changes state, all its dependents are notified and updated automaticaaly.
//
// Author : ZAsia
// Date : 15/05/16
// Warning : In practice, declaration and implementation should
// be separated(.h and .cpp).
///
#include
#include
#include
using namespace std;
typedef string State;
#define SAFE_DELETE_PTR(ptr) if (ptr) { delete ptr; ptr = nullptr; }
// forward declaration
class Subject;
// Observer
// - defines an updating interface for objects that should be notified of changes
// in a subject.
class Observer
{
public:
virtual ~Observer() { }
virtual void Update(Subject *theChangedSubject) = 0;
protected:
Observer() { }
};
// Subject
// - knows its observer. Any number of Obsever objects may observe a subject.
// - provides an interface for attaching and detaching Observer objects.
class Subject
{
public:
virtual ~Subject()
{
if (_observers)
{
delete _observers;
}
}
virtual void Attach(Observer *observer)
{
_observers->push_back(observer);
}
virtual void Detach(Observer *observer)
{
_observers->remove(observer);
}
virtual void Notify()
{
for (list
::iterator iter = _observers->begin();
iter != _observers->end(); ++iter)
{
(*iter)->Update(this);
}
}
protected:
Subject() : _observers(new list
) { } private: list
*_observers; }; // ConcreteSubject // - stores state of interest to ConcreteObserver objects. // - sends notification to its observers when its state changes. class ConcreteSubject : public Subject { public: ConcreteSubject(State state = "") : _state(state) { } State GetState() { return _state; } void SetState(State state) { _state = state; } private: State _state; }; // ConcreteObserver // - maintains a reference to a ConcreteSubject object. // - stores state that should stay consistent with subjects's. // - implements the Observer updating interface to keep its state consistent // with the subject's. class ConcreteObserver : public Observer { public: ConcreteObserver(Subject *subject) : _subject(subject) { } virtual void Update(Subject *theChangedSubject) { cout << "ConcreteObserver::Update--> now state is " << dynamic_cast
(theChangedSubject)->GetState() << endl; } private: Subject *_subject; }; // collaborations // - ConcreteSubject notifies its observers whenever a change occurs that could // make its observers' state inconsistent with its own. // - After being informed of a change in the concrete subject, a ConcreteObserver // object may query the subject for information. ConcreteObserver uses this // information to reconcile its state with that of the subject. // - Note how the Observer object that initiates the change request postpones its // update until it gets a notification from the subject. Notify is not always // called by the subject. It can be called by an observer or by another kind of // object entirely. int main() { ConcreteSubject *pConcreteSubject = new ConcreteSubject(); Observer *pObserverA = new ConcreteObserver(pConcreteSubject); Observer *pObserverB = new ConcreteObserver(pConcreteSubject); pConcreteSubject->Attach(pObserverA); pConcreteSubject->Attach(pObserverB); pConcreteSubject->SetState("student"); pConcreteSubject->Notify(); pConcreteSubject->Detach(pObserverB); pConcreteSubject->SetState("worker"); pConcreteSubject->Notify(); SAFE_DELETE_PTR(pConcreteSubject); SAFE_DELETE_PTR(pObserverA); SAFE_DELETE_PTR(pObserverB); return 0; } // 1. All a subject knows is that it has a list of observers, each conforming to // the simple interface of the abstract Observer class.
DesignPatterns_Observer
最新推荐文章于 2024-06-04 10:12:06 发布