🔭Observer
The Observer pattern provides a way to subscribe and unsubscribe to and from these events for any object that implements a subscriber interface.
Usage examples
The Observer pattern is pretty common in C++ code, especially in the GUI components. It provides a way to react to events happening in other objects without coupling to their classes.
Identification
The pattern can be recognized by subscription methods, that store objects in a list, and by calls to the update method issued to objects in that list.
Pros & Cons
Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher’s code (and vice versa if there’s a publisher interface).
You can establish relations between objects at runtime.
Subscribers are notified in random order.
Graphic Visual


Example
The following example shows the structure of the Observer design pattern, focusing on answering these questions:
What classes does it consist of?
What roles do these classes play?
In what way elements of the pattern are related?
Conceptual example
main.cpp
#include <iostream>
#include <list>
#include <string>
class IObserver {
//define Observer Interface
//good practice when dealing with inheritance
public:
virtual ~IObserver(){}; //virtual destructor
//pure (=0) virtual method
virtual void Update(const std::string &message_from_subject) = 0;
};
class ISubject {
//define Subject Interface
public:
virtual ~ISubject(){}; //virtual destructor
//Pure virtual methods
//Defines a way to attach (register) an observer object to the subject.
//It takes a pointer to an IObserver object as input.
virtual void Attach(IObserver *observer) = 0;
//Defines a way to detach (unregister) an observer object from the subject.
//It also takes a pointer to an IObserver object as input.
virtual void Detach(IObserver *observer) = 0;
//Defines a way for the subject to notify all attached observers.
//Typically involves sending some data to the registered observers.
virtual void Notify() = 0;
};
/*
The Subject owns some important state and notifies observers when the state
changes.
*/
class Subject : public ISubject {
//creates a derived class from ISubject
public:
//define desrtuctor behavior
virtual ~Subject() {
std::cout << "Goodbye, I was the Subject.";
}
/**
* The subscription management methods.
*/
void Attach(IObserver *observer) override {
//add the observer at the end of the observer list
list_observer_.push_back(observer);
}
void Detach(IO *observer) override {
//remove the observer from the observer list
list_observer_.remove(observer);
}
void Notify() override {
//reach the start of the observer list
std::list<IObserver *>::iterator iterator = list_observer_.begin();
HowManyObserver();
while (iterator != list_observer_.end()) {
(*iterator)->Update(message_);
++iterator;
}
}
void CreateMessage(std::string message = "Empty") {
this->message_ = message;
Notify();
}
void HowManyObserver(){
//print out how many observers are listening
std::cout << "There are" << list_observer_.size() << " observers in the list";
}
/*
* Usually, the subscription logic is only a fraction of what a Subject can
* really do. Subjects commonly hold some important business logic, that
* triggers a notification method whenever something important is about to
* happen (or after it).
*/
void SomeBusinessLogic(){
this->message_ = "change message";
Notify();
std::cout << "I'm about to do some cool things, wow!";
}
private:
std::list<IObserver *> list_observer_;
std:: message_;
};
class Observer : public IObserver {
public:
Observer(Subject &subject) : subject_(subject) {
this->subject_.Attach(this);
std::cout << "I'm the Observer" << ++Observer::static_number_ << ".";
this->number_ = Observer::static_number_;
}
virtual ~Observer(){
std::cout << "Goodbye, I was the Observer " << this->number_ << ".";
}
void Update(const std::string &message_from_subject) override {
message_from_subject_ = message_from_subject;
PrintInfo();
}
void RemoveMeFromTheList() {
subject_.Detach(this);
std::cout << "Observer \"" << number_ << "\" removed from the list.\n";
}
void PrintInfo() {
std::cout << "Observer " << this->number_ << this->message_from_subject_;
}
private:
std::string message_from_subject_;
Subject &subject_;
static int static_number_;
int number_;
};
int Observer::static_number_ = 0;
void ClientCode() {
Subject *subject = new Subject;
Observer *observer1 = new Observer(*subject);
Observer *observer2 = new Observer(*subject);
Observer *observer3 = new Observer(*subject);
Observer *observer4;
Observer *observer5;
subject->CreateMessage("Hello World! :D");
observer3->RemoveMeFromTheList();
subject->CreateMessage("The weather is hot today! :p");
observer4 = new Observer(*subject);
observer2->RemoveMeFromTheList();
observer5 = new Observer(*subject);
subject->CreateMessage("My new car is great! ;)");
observer5->RemoveMeFromTheList();
observer4->RemoveMeFromTheList();
observer1->RemoveMeFromTheList();
delete observer5;
delete observer4;
delete observer3;
delete observer2;
delete observer1;
delete subject;
}
int main() {
ClientCode();
return 0;
}Last updated