C++ Observer Implementation

The Observer design pattern is used for state change notifications. An object called subject (or publisher) has a list of dependents, called observers (or subscribers). When the subject changes state, all its dependents are notified by calling a method. The Observer pattern is useful for the implementation of event handling.

UML diagram


The observer interface has an abstract method used for notifications and the subject has methods for attachment and detachment of observers.

The typical C++ implementation is shown below:

class IObserver {
public:
        virtual void update(CSubject const& value) = 0;
};

class CSubject
{
public:
    CSubject()
    {
    }

    void attachObserver(IObserver* pObserver) const
    {
        assert(pObserver);
        // Add mutex if you want to make the code thread safe
        m_svObservers.push_back(pObserver);
    }

    void detachObserver(IObserver* pObserver) const
    {
        assert(pObserver);
        // Add mutex if you want to make the code thread safe
        typename TObserversVector::iterator itToBeDetached;
        for (itToBeDetached = m_svObservers.begin();itToBeDetached != m_svObservers.end(); ++itToBeDetached) {
            if (pObserver != *itToBeDetached)
                continue;

            m_svObservers.erase(itToBeDetached);
            break;

        }
    }
protected:
    void notify()
    {
        // Add mutex if you want to make the code thread safe
        typename TObserversVector::iterator itObserver;
        for (itObserver = m_svObservers.begin();itObserver != m_svObservers.end();++itObserver)
            (*itObserver)->update(*this);
    }
private:
    typedef std::vector<IObserver*> TObserversVector;
    mutable TObserversVector m_svObservers;
};

Since I come from a Delphi background, one possible use of Observer for me is the implementation of properties. This way the observers can be notified when the value of the property has changed:

Observable Property


It’s implemented using templates. A property can be declared like that:

CPublisherT<bool>	ptBooleanProperty;

The subscribers should be derived from ISubscriberT:

class CBoolSubscriber : public ISubscriberT<bool>
{
...
public:
    void update(bool const& value)
    {
        ...
    };
};

When you assign a new value to the property

ptBooleanProperty = true;

all registered subscribers will be notified about the change.

The full source code of the observable property is listed bellow and is available for download.

#include <vector>
#include <assert.h>

template<typename T>
class ISubscriberT {
public:
        virtual void update(T const& value) = 0;
};

template<typename T>
class CPublisherT
{
public:
    CPublisherT(T& value) :
		m_pValue(&value)
    {
    }

    CPublisherT(CPublisherT<T> const& publisher)
    {
        m_svSubscribers = publisher.m_svSubscribers;
	m_pValue = publisher.m_pValue;
	notify();
    }

    CPublisherT<T>& operator=(T& rhs)
    {	
	*m_pValue = rhs;
	notify();
	return (*this);
    }

    bool operator==(T& rhs) const
    {	
	return (*m_pValue == rhs);
    }

    bool operator!=(T& rhs) const
    {	
  	return (*m_pValue != rhs);
    }

    operator T const&() const
    {
	return *m_pValue;
    }

    void attachSubscriber(ISubscriberT<T>* pSubscriber) const
    {
        assert(pSubscriber);
        // Add mutex if you want to make the code thread safe
        m_svSubscribers.push_back(pSubscriber);
    }

    void detachSubscriber(ISubscriberT<T>* pSubscriber) const
    {
        assert(pSubscriber);
        // Add mutex if you want to make the code thread safe
        typename TSubscribersVector::iterator itToBeDetached;
        for (itToBeDetached = m_svSubscribers.begin();itToBeDetached != m_svSubscribers.end(); ++itToBeDetached) {
            if (pSubscriber != *itToBeDetached)
                continue;

            m_svSubscribers.erase(itToBeDetached);
            break;
        }
    }

	void notify()
    {
        // Add mutex if you want to make the code thread safe
        typename TSubscribersVector::iterator itSubscriber;
        for (itSubscriber = m_svSubscribers.begin();itSubscriber != m_svSubscribers.end();++itSubscriber)
            (*itSubscriber)->update(*m_pValue);
    }
private:
    typedef std::vector<ISubscriberT<T>*> TSubscribersVector;
    mutable TSubscribersVector m_svSubscribers;
    T*	m_pValue;
};
You can leave a response, or trackback from your own site.

2 responses to “C++ Observer Implementation”

  1. Legi says:

    Sorry to comment here, but seems that fennec packages are not on the repository, shame as i wanted to update to 17 version.

    Thx for your work.

  2. Vladislav says:

    Actually it’s only one package, but it’s in the repository. I updated through the repository and a colleague of mine did the same. I’m using free web hosting, so may be the site was down.
    Can you please try once again?
    P.S.
    You’re trying to do:
    apt-get update
    apt-get upgrade
    Am I right?

Leave a Reply