The Observer Design Pattern follows one of the most important principles of Object Oriented Programming. This principle states:
Strive for loosely coupled designs between objects that interact.
It means that your classes should be able to interact with each other, but have little knowledge about each other. This essentially means that your classes should be loosely coupled.
A good analogy that helps understand how the Observer Design Pattern works is a newspaper subscription.
The newspaper nor the subscriber have internal knowledge about each other, yet they are able to interact. The newspaper updates the subscriber with news, the subscriber reads them.
Implementing the Observer Design Pattern
We are going to implement the Observer Design Pattern in C++. We are going to make use of abstract classes to implement the concept of Interfaces.
We will create two interfaces whose names are: Subject and Observer. The Subject interface will contain virtual methods that will register, remove and notify an Observer object.
The Observer interface will have one virtual method that will be updated with information from the Subject object.
We will then create two concrete classes that will implement the virtual methods of each interface.
The class that will implement the Subject interface will act as a News Station. It will register and notify its subscribers on the latest news.
The class that implements the Observer interface will act as a Subscriber. It will subscribe itself to the Subject interface and receive any notification.
Implementation of the Subject Interface
The implementation of the Subject interface is quite simple. Recall that to create an interface in C++, you must make the class an abstract class by making its methods virtual.
Listing 1 shows the implementation of the subject interface.
Listing 1. Subject Interface
#include "Observer.h"
class Subject{
public:
virtual void registerObserver(Observer *obs)=0;
virtual void removeObserver(Observer *obs)=0;
virtual void notifyObserver()=0;
};
All three methods in the subject class must be virtual classes. A concrete class will be inherited from this class and will be required to implement all three virtual methods.
Implementation of the Observer Interface
The implementation of the Observer interface follows the same logic as the Subject interface. However, this interface only requires one virtual method.
Listing 2 shows the implementation of the Observer interface.
A concrete class will also be inherited from this class and will implement the update virtual method.
Listing 2. Observer Interface
class Observer{
public:
virtual void update()=0;
};
Implementing the NewsStation class
Listing 3 & 4 shows the implementation of the NewsStation class.
The concrete class contains a Vector which stores the Observer objects.
Listing 3. NewsStation header
class NewsStation:public Subject{
public:
//vector to store all register observers
vector<Observer*> observers;
//constructor
NewsStation(){};
//method to register observer
void registerObserver(Observer *obs);
//method to remove observer
void removeObserver(Observer *obs);
//method to notify observer
void notifyObserver();
};
When the NewsStation class needs to notify its Subscribers, it simply iterates through the vector and sends the update.
Listing 4. Newspaper method implementations
void NewsStation::registerObserver(Observer *obs){
observers.push_back(obs);
}
void NewsStation::removeObserver(Observer *obs){
observers.erase(find(observers.begin(), observers.end(), obs));
}
void NewsStation::notifyObserver(){
//search for all register observers
for (int i=0; i<observers.size(); i++) {
Observer *observer=(Observer*)observers[i];
//call the observer method- update
observer->update();
}
}
Implementing the NewsReader class
The implementation of the NewsReader class is shown in listing 5 & 6.
Note that we have a pointer to the Subject interface as shown in listing 5.
Upon creation of the NewsReader class, we register the object to the Subject interface, in this case to the NewsStation class.
Listing 5. NewsReader header
#include "Subject.h"
class NewsReader:public Observer{
public:
Subject *subject;
//Note that we are registering the newsreader to the Subject class during initialization
NewsReader(Subject *sub){
subject=sub;
subject->registerObserver(this);
}
void update();
};
Listing 6 shows the implementation of Update method. It simply outputs the message that the reader has been notified.
Listing 6. NewsReader method implementation
void NewsReader::update(){
//Output:"I am the news reader that was notified"
cout<<"I am the news reader that was notified"<<endl;
}
Putting it all together
Let’s see the Observer Design Pattern in action.
Listing 7 shows the creation of the News Station. Note how I'm coding to the interface Subject, not to the implementation NewsStation (line 1).
Listing 7.
#include "NewsReader.h"
#include "NewsStation.h"
#include "NeighborReader.h"
int main(int argc, const char * argv[])
{
//1. create our newsStation. NOTE how I'm coding to the interface "subject", not to the implementation "newsStation"
Subject *newsStation=new NewsStation();
//2. creating our newsReader class. When the constructor gets called, the newsReader class is register with the newsStation
Observer *newsReader=new NewsReader(newsStation);
//3. creating our neighborReader class. When the constructor gets called, the neighborReader class is register with the newsStation
Observer *neighborReader=new NeighborReader(newsStation);
//4. the newsStation notifies all observers.
newsStation->notifyObserver();
return 0;
}
In line 2, we create an instance of the NewsReader class. When the constructor gets called, the NewsReader object is register with the NewsStation.
Line 4, simply notifies all the subscribers.
Line 3 shows the power of the Observer Design Pattern. The NeighborReader object is able to subscribe to the NewsStation object because it implements the methods in the Observer interface.
You can create as many new classes as you wish. As long as they implement the methods in the Observer interface, they will be able to register as subscribers, unregister and receive any updates from the NewsStation.
All of the classes are loosely coupled.
Source code
You can download the source code for the Observer Design Pattern here.