///////////////////////////////////////////////////////////////////////////////
// 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
最新推荐文章于 2021-03-04 11:34:48 发布