Avoiding Circular Dependencies using Observer Patterns in C++

The basic concept is when you want information stored in one object, called the Model (or subject) to be watched by other objects, called Views (or observers). When information changes in the Model, all views attached to the Model should be notified and their statuses updated accordingly. In simpler terms, class A needs to know about class B, and vice versa, but while avoiding circular dependencies while doing so. The classical implementation is described in the classic Design Patterns: Elements of Reusable Object Oriented Software by the ‘Gang of Four’ (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides):

As seen from the class diagram, all View objects are derived from the Observer class while all Models (subjects) are derived from the Subject class.

Example usage

void main()
{
	B* b = new B;
	A* a = new A;	
	
	// Set the 'B' object inside of A
	// and set its observer(s)
	a->Init( b );

	// Cause the DoStuff function to get called in A:
	b->Notify();

	delete a;
	delete b;
}

Observer Class

#include "B.h"
#include <iostream>

class A : public Observer
{
public:
	void Init( B* b );	
	void DoStuff();	
private:
	B* m_b;
};
#include "A.h"

void A::Init( B* b )
{
	m_b = b; 	
	m_b->AddObserver( this );
}

void A::DoStuff() 
{ 
	std::cout 

Subject class

#include <vector>
#ifndef _B_H
#define _B_H

class Observer;

class B
{
public:
	~B();
	void AddObserver( Observer* ob );
	void Notify();
private:
	std::vector<Observer*> ob_set;
};

class Observer
{
public:
	virtual void DoStuff() = 0;
};

#endif
void B::Notify()
{
   for ( std::vector<Observer*>::iterator it = ob_set.begin();
         it != ob_set.end();
	     it++ )
   {
	Observer* ob = *it;
	ob->DoStuff();
   }	
}

Example Visual Studio 2008 code sample downloadable from here




Leave a Reply