Click here to Skip to main content
Click here to Skip to main content

Understanding and Implementing Observer Pattern in C++

By , 25 Mar 2012
 

Introduction

This article presents the basics of Observer Pattern, when to use it and how to implement it in C++. I have posted a similar article that talks about the Observer pattern in C#. The main aim of this article will be to implement the observer pattern in C++.

Background

Many a times, we need one part of our application updated with the status of some other part of the application. One way to do this is to have the receiver part repeatedly check the sender for updates but this approach has two main problems. First, it takes up a lot of CPU time to check the new status and second, depending on the interval we are checking for change we might not get the updates "immediately".

This problem has one easy solution, i.e., Observer Pattern. This is my own second article on Observer Pattern. I have a similar article talking about Observer Implementation in C#. I think this article is also worth sharing, as it could be useful for the C++ beginners and also the valuable comments I get on the article will let me learn more.

Here is the class diagram for Observer Pattern(Reference:  GoF Design Patterns)


Using the Code

Let us now discuss all the classes one by one:

  • Subject: This class keeps track of all the observers and provides the facility to add or remove the observers. Also it is the class that is responsible for updating the observers when any change occurs. In our solution, we have ASubject implemented for the same purpose.
  • ConcreteSubject: This class is the real class that implements the Subject. This class is the entity whose change will affect other objects. We have DummyProject class implemented for the same.
  • Observer: This represents an interface that defines the method that should be called whenever there is change. We have implemented this as IObserver.
  • ConcreteObserver: This is the class which needs to keep itself updated with the change. This class just needs to implement the Observer and register itself with the ConcreteSubject and it is all set to receive the updates. We have Shop class in our application serving the same purpose.

The Subject: ASubject

//Header File
#pragma once
#include <vector>
#include <list>
#include "shop.h"

class ASubject
{
    //Lets keep a track of all the shops we have observing
    std::vector<Shop*> list;

public:
    void Attach(Shop *product);
    void Detach(Shop *product);
    void Notify(float price); 
};

//CPP File
#include "ASubject.h"
#include <algorithm>

using namespace std;

void ASubject::Attach(Shop *shop)
{
    list.push_back(shop);
}
void ASubject::Detach(Shop *shop)
{    
    list.erase(std::remove(list.begin(), list.end(), shop), list.end());    
}

void ASubject::Notify(float price)
{
    for(vector<Shop*>::const_iterator iter = list.begin(); iter != list.end(); ++iter)
    {
        if(*iter != 0)
        {
            (*iter)->Update(price);
        }
    }
}

The ConcreteSubject: DummyProduct

//Header File
#pragma once
#include "ASubject.h"

class DummyProduct : public ASubject
{
public:
    void ChangePrice(float price);
};

//CPP File
#include "DummyProduct.h"

void DummyProduct::ChangePrice(float price)
{
    Notify(price);
}

The Observer: IObserver

#pragma once

class IObserver
{
public:
    virtual void Update(float price) = 0;
};

The ConcreteObserver: Shop

//Header File
#pragma once
#include <iostream>
#include <string>
#include "IObserver.h"

class Shop : IObserver
{
    //Name of the Shop
    std::string name;
    float price;
public:
    Shop(std::string n); 
    void Update(float price);          
};

//CPP File
#include "Shop.h"

Shop::Shop(std::string name)
{
    this->name = name;
}

void Shop::Update(float price)
{
    this->price = price;

    //Lets print on console just to test the working
    std::cout << "Price at "<< name << " is now "<< price << "\n";
}

Testing the Code

int main(int argc, char* argv[])
{
    DummyProduct product;
                    
    // We have four shops wanting to keep updated price set by product owner
    Shop shop1("Shop 1");
    Shop shop2("Shop 2");

    product.Attach(&shop1);
    product.Attach(&shop2);

    //Now lets try changing the products price, this should update the shops automatically
    product.ChangePrice(23.0f);

    //Now shop2 is not interested in new prices so they unsubscribe
    product.Detach(&shop2);            

    //Now lets try changing the products price again
    product.ChangePrice(26.0f);

    getchar();
    return 0;
}

Points of Interest

This article covers the basics of Observer pattern and provides a basic implementation in C++. I have also implemented the same in C#. What I learnt from it is how the observer pattern works and what are the similarities and differences in implementing it in C++ and C#.

History

  • 10 Feb, 2012: Simple and rudimentary implementation of Observer pattern in C++
  • 26 March 2012: Changed the class diagram.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rahul Rajat Singh
Software Developer (Senior)
India India
Member
I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems.
 
Some CodeProject Achievements:
  • 9th in Best Web Dev article of March 2013
  • 7th in Best Web Dev article of January 2013
  • 2nd in Best C# article of December 2012
  • 5th in Best overall article of December 2012
  • 5th in Best C# article of October 2012
  • 4th in Best Web Dev article of September 2012
  • 3rd in Best C# article of August 2012
  • 5th in Best Web Dev article of August 2012
  • 5th in Best Web Dev article of July 2012
  • 3rd in Best Overall article of June 2012
  • 2nd in Best Web Dev article of June 2012
  • 5th in Best Web Dev article of May 2012
  • 6th in Best Web Dev article of April 2012
  • 4th in Best C++ article of April 2012
  • 5th in Best C++ article of March 2012
  • 7th in Best Web Dev article of March 2012
  • 5th in Best Web Dev article of February 2012
  • 7th in Best Web Dev article of February 2012
  • 9th in Best Web Dev article of February 2012
  • 5th in Best C++ article of February 2012

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSeems violating the pattern....memberMusthafa (Member 379898)24 Apr '13 - 16:44 
when we look at observer pattern diagram, seems it impose to implement the subject and object methods in concrete subject & concrete object. but you implemented in subject & object itself. but at the same time, it is ok since it also fulfills the single responsibility principle. I am not sure, but Just confused, any one can clarify it?
 
Thanks
GeneralVote of 5memberr.warhekar21 Feb '13 - 22:43 
Really very useful to understand Observer.
GeneralMy vote of 5memberRASPeter23 May '12 - 9:47 
Clear, concise, and the code works
GeneralMy vote of 1 [modified]memberFerretallicA26 Mar '12 - 13:20 
As usual you are just regurgitating things and providing little (if any) context to assist anyone who is actually LEARNING, and the examples provided are very thin if used as a reference for someone who already understands the pattern and wants to see a C implementation.

modified 26 Mar '12 - 19:30.

GeneralMy vote of 1memberzennie19 Mar '12 - 21:49 
This article should not be in this section. There is not C in the article itself and only a very limited obviously layman's attempt at a C implementation. This should be moved to the C# section.
SuggestionUsing templatesmemberJohn Wellbelove13 Feb '12 - 22:15 
The usefulness of the base classes can be improved by templating them. This would allow the Notify and Update fuctions to be able to send data based on a type dictated by the template parameter, rather than being fixed.
 
template <typename TUpdate>
class IObserver
{
public:
    virtual void Update(TUpdate value) = 0;
};

GeneralMy vote of 4 [modified]memberKjellKod.cc13 Feb '12 - 10:20 
14th February: Edit to remove misunderstanding
 
Nice short and to the point. I gave it a four as it showed very clear how an Observer implementation could work.
 
1) Have you given any thoughts to push vs pull of the data after/with the notification?
 
2) the Observer pattern is a great teaching example.. However., What if classes need to publish/subscribe to/from several other entities and data? It is easy to see how the code can deteriorate with just a few multiple inheritances.
 
I.m.h.o a much improved technique is "signals and slots". It is really just a generation improvement of the Observer pattern but relying on composition instead of inheritance which greatly helps in keeping the design "clean". It takes the loosely coupled Observer pattern one step further and solves exactly the same problem but without inheritance. In case of Huge amounts of data this is also more efficient since virtual calls can be avoided.
 
There exist a multitude of "signal-and-slots" implementations from the original Qt's (the only threadsafe signal communication) using "mock" to more advanced like boost::signals or even for embedded software like my own (simple yet efficient) ksignals (http://sites.google.com/site/kjellhedstrom2/signalandslots)
 
Check out signals-and-slots. I think you will like it.
 
Thanks again for the article. I am looking forward to your next

modified 14 Feb '12 - 9:00.

GeneralRe: My vote of 4memberStefan_Lang14 Feb '12 - 0:41 
KjellKod.cc wrote:
2) In my opinion the Observer pattern is a great teaching example that often (not always) is best to stay as just that, an example.

I've found the observer pattern to be very useful in embedded programming, where other architectures for communicating events (such as broadcasting) failed the real-time requirements: in various parts of our applications it was crucial that certain actuators (such as stepper motors) were stopped (or started) immediately when a certain sensor reported a change, and having every subsystem check every signal was simply too slow for our purposes.
 
I don't know enough about signals and slots implementations to judge whether that would have worked as well (or better), but I do know that the observer pattern worked perfectly for our requirements back then.
GeneralRe: My vote of 4memberKjellKod.cc15 Feb '12 - 3:19 
Hi Stefan and thank you for your reply.
 
I had to modify my initial comment as I realized that it came off as a "against Observer pattern" comment. Observer pattern is a beautiful way to make a loosely coupled system and I absolutely do not want to shoot that down.
 
What I wanted to say is that signals and slots come with all the advantages of Observer pattern but less of its disadvantages. If Observer pattern is great, then signal-and-slots is great++ Wink | ;)
 
Let me give you an example:
For reasons similar to your own we used the Observer pattern in an embedded realtime system [uVelocity on a 300Mhz Power-PC]. It was decided that the Observer type we would use would have one type of message per "inheritance" it is possible (in many ways) to have it serve different types of messages through one IObserver relationship but this will make the design less clear.
 
As the scope and requirements changed we had to use many more Observers, per recipient than the idea was from the beginning. Multiple inheritance is to be avoided for many reasons and we probably encountered them all ...
 
We then did a make over and exchanged this communication scheme for a templated signals-and-slots mechanism.
 
Result: Less overhead (faster), clearer design, no more inheritance needed to connect sender to recipient(s).
 
Observer pattern is great, but if there exist a way of giving the same functionality but without inheritance, by composition, then maybe it is worthwhile checking out?
GeneralRe: My vote of 4memberStefan_Lang16 Feb '12 - 23:12 
I've looked over signals and slots, and found them to be not that different from the observer pattern. The main difference seems to be that it separates the logic (i. e. who signals what to whom) is separated from the observers.
 
I can see why that would make sense in some systems, but from an OO point of view, most objects that I can think of in the role of an observer 'know' very well what signals they should listen for, and therefore don't need that kind of separation. You may argue that an observer may not know what types of signals there may be out there, and therefore they may not know all the signals they should react to - but if that is the case, then how should the observer know how to react to that signal it doesn't know of? What's more, whether or not an observer wishes to be notified of a certain event may depend on its current state that an external object may not be aware of!
 
My opinion is that if there is a signal that an observer should react to, then it must 'know' of it it in the sense that it knows its interface (or an interface the observer can use to interact with it), and use that interface to register its wish to be notified.
 
Why must there be a separate object hat is responsible for registering the observer? And: is it even sensible to have such an object? In the system I mentioned in my previous post we've found that we had to strictly limit the notifications to the absolute minimum, just to be able to satisfy the hard real time conditions! We simply couldn't afford to wake up every observer every time a signal that might interest them popped up. Instead, we needed the observers to be able to switch off notifications during phases where they didn't matter - and only the observers themselves knew when that would be.
 
When I think about it, the way we implemented the observer pattern left it to each subsystem to decide for themselves whether it was the observer who did the registration or an external object. In fact, we could have one independent class for each association of a signal to an observer. However, we found that in all but a few cases it simply didn't make sense: most of the observers had to be able to switch notifications on and off at all times, just so they wouldn't get swamped by them. Anything short of that would have led to violations of hard real time conditions.
 
I don't argue the flexibility of signals and slots, but my experience shows that you trade a significant amount of performance for this flexibility. Depending on the system you implement, wou will have to decide which is your priority.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 26 Mar 2012
Article Copyright 2012 by Rahul Rajat Singh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid