An abstract class defines the Observer interface:
This implementation supports multiple subjects for each observer. The subject passed to the Update operation lets the observer determine which subject changed when it observes more than one.class Subject; class Observer { public: virtual ~ Observer(); virtual void Update(Subject* theChangedSubject) = 0; protected: Observer(); };
Similarly, an abstract class defines the Subject interface:
ClockTimer is a concrete subject for storing and maintaining the time of day. It notifies its observers every second. ClockTimer provides the interface for retrieving individual time units such as the hour, minute, and second.class Subject { public: virtual ~Subject(); virtual void Attach(Observer*); virtual void Detach(Observer*); virtual void Notify(); protected: Subject(); private: List *_observers; }; void Subject::Attach (Observer* o) { _observers->Append(o); } void Subject::Detach (Observer* o) { _observers->Remove(o); } void Subject::Notify () { ListIterator i(_observers); for (i.First(); !i.IsDone(); i.Next()) { i.CurrentItem()->Update(this); } }
The Tick operation gets called by an internal timer at regular intervals to provide an accurate time base. Tick updates the ClockTimer's internal state and calls Notify to inform observers of the change:class ClockTimer : public Subject { public: ClockTimer(); virtual int GetHour(); virtual int GetMinute(); virtual int GetSecond(); void Tick(); };
Now we can define a class DigitalClock that displays the time. It inherits its graphical functionality from a Widget class provided by a user interface toolkit. The Observer interface is mixed into the DigitalClock interface by inheriting from Observer.void ClockTimer::Tick () { // update internal time-keeping state // ... Notify(); }
Before the Update operation draws the clock face, it checks to make sure the notifying subject is the clock's subject:class DigitalClock: public Widget, public Observer { public: DigitalClock(ClockTimer*); virtual ~DigitalClock(); virtual void Update(Subject*); // overrides Observer operation virtual void Draw(); // overrides Widget operation; // defines how to draw the digital clock private: ClockTimer* _subject; }; DigitalClock::DigitalClock (ClockTimer* s) { _subject = s; _subject->Attach(this); } DigitalClock::~DigitalClock () { _subject->Detach(this); }
An AnalogClock class can be defined in the same way.void DigitalClock::Update (Subject* theChangedSubject) { if (theChangedSubject == _subject) { Draw(); } } void DigitalClock::Draw () { // get the new values from the subject int hour = _subject->GetHour(); int minute = _subject->GetMinute(); // etc. // draw the digital clock }
The following code creates an AnalogClock and a DigitalClock that always show the same time:class AnalogClock : public Widget, public Observer { public: AnalogClock(ClockTimer*); virtual void Update(Subject*); virtual void Draw(); // ... };
Whenever the timer ticks, the two clocks will be updated and will redisplay themselves appropriately.ClockTimer* timer = new ClockTimer; AnalogClock* analogClock = new AnalogClock(timer); DigitalClock* digitalClock = new DigitalClock(timer);