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
#pragma once
#include <vector>
#include <list>
#include "shop.h"
class ASubject
{
std::vector<Shop*> list;
public:
void Attach(Shop *product);
void Detach(Shop *product);
void Notify(float price);
};
#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
#pragma once
#include "ASubject.h"
class DummyProduct : public ASubject
{
public:
void ChangePrice(float price);
};
#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
#pragma once
#include <iostream>
#include <string>
#include "IObserver.h"
class Shop : IObserver
{
std::string name;
float price;
public:
Shop(std::string n);
void Update(float price);
};
#include "Shop.h"
Shop::Shop(std::string name)
{
this->name = name;
}
void Shop::Update(float price)
{
this->price = price;
std::cout << "Price at "<< name << " is now "<< price << "\n";
}
Testing the Code
int main(int argc, char* argv[])
{
DummyProduct product;
Shop shop1("Shop 1");
Shop shop2("Shop 2");
product.Attach(&shop1);
product.Attach(&shop2);
product.ChangePrice(23.0f);
product.Detach(&shop2);
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.