C++ Observer Pattern Example

In this article, we will learn how to use and implement the Observer Pattern in C++ with an example.

Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
Observer defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The pattern has a behavioral purpose and applies to the objects.

C++ Observer Pattern Example

The below diagram shows the generic structure of the Observer Pattern:
Let's refer to the above structure to create an example to demonstrates the usage of the Observer Pattern.
#include <iostream>
#include <vector>

class Subject;

/*
 * Observer
 * defines an updating interface for objects that should be notified
 * of changes in a subject
 */
class Observer
{
public:
    virtual ~Observer() {}

    virtual int getState() = 0;
    virtual void update( Subject *subject ) = 0;
};

/*
 * Concrete Observer
 * stores state of interest to ConcreteObserver objects and
 * sends a notification to its observers when its state changes
 */
class ConcreteObserver : public Observer
{
public:
    ConcreteObserver( const int state ) :
        observer_state( state ) {}

    ~ConcreteObserver() {}

    int getState()
    {
        return observer_state;
    }

    void update( Subject *subject );

private:
    int observer_state;
};

/*
 * Subject
 * knows its observers and provides an interface for attaching
 * and detaching observers
 */
class Subject
{
public:
    virtual ~Subject() {}

    void attach( Observer *observer )
    {
        observers.push_back(observer);
    }

    void detach( const int index )
    {
        observers.erase( observers.begin() + index );
    }

    void notify()
    {
        for ( unsigned int i = 0; i < observers.size(); i++ )
        {
            observers.at( i )->update( this );
        }
    }

    virtual int getState() = 0;
    virtual void setState( const int s ) = 0;

private:
    std::vector<Observer*> observers;
};

/*
 * Concrete Subject
 * stores state that should stay consistent with the subject's
 */
class ConcreteSubject : public Subject
{
public:
    ~ConcreteSubject() {}

    int getState()
    {
        return subject_state;
    }

    void setState( const int s )
    {
        subject_state = s;
    }

private:
    int subject_state;
};

void ConcreteObserver::update( Subject *subject )
{
    observer_state = subject->getState();
    std::cout << "Observer state updated." << std::endl;
}


int main()
{
    ConcreteObserver observer1( 1 );
    ConcreteObserver observer2( 2 );

    std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
    std::cout << "Observer 2 state: " << observer2.getState() << std::endl;

    Subject *subject = new ConcreteSubject();
    subject->attach( &observer1 );
    subject->attach( &observer2 );

    subject->setState( 10 );
    subject->notify();

    std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
    std::cout << "Observer 2 state: " << observer2.getState() << std::endl;

    delete subject;
    return 0;
}

Output

Observer 1 state: 1
Observer 2 state: 2
Observer state updated.
Observer state updated.
Observer 1 state: 10
Observer 2 state: 10

When to Use Observer Pattern 

Use the Observer pattern when changes to the state of one object may require changing other objects, and the actual set of objects is unknown beforehand or changes dynamically.
Use the pattern when some objects in your app must observe others, but only for a limited time or in specific cases.

Comments