The Observer pattern is a software design pattern where an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes. We can implement this pattern in C++ using references for a clean and efficient design.
Here's a simple implementation:
#include <iostream>
#include <string>
#include <vector>
class Observer {
public:
virtual void Update(
const std::string& message) = 0;
virtual ~Observer() = default;
};
class Subject {
private:
std::vector<Observer*> observers;
std::string state;
public:
void Attach(Observer& observer) {
observers.push_back(&observer);
}
void Detach(Observer& observer) {
observers.erase(std::remove(
observers.begin(),
observers.end(),
&observer
), observers.end());
}
void SetState(const std::string& newState) {
state = newState;
Notify();
}
void Notify() {
for (auto observer : observers) {
observer->Update(state);
}
}
};
class ConcreteObserver : public Observer {
private:
std::string name;
public:
ConcreteObserver(const std::string& observerName)
: name{observerName} {}
void Update(const std::string& message) override {
std::cout << name << " received message: "
<< message << '\n';
}
};
int main() {
Subject subject;
ConcreteObserver observer1{"Observer 1"};
ConcreteObserver observer2{"Observer 2"};
subject.Attach(observer1);
subject.Attach(observer2);
subject.SetState("Hello, observers!");
subject.Detach(observer2);
subject.SetState("Observer 2 won't see this.");
}
Observer 1 received message: Hello, observers!
Observer 2 received message: Hello, observers!
Observer 1 received message: Observer 2 won't see this.
Let's break this down:
Observer
interface with a pure virtual Update()
method.Subject
class maintains a list of observer pointers. We use pointers here because std::vector
can't store references directly.Attach()
and Detach()
methods in Subject
take references to Observer
objects. This provides a clean syntax for the user of the class and ensures that null observers can't be attached.SetState()
is called, it updates the state and calls Notify()
, which updates all observers.ConcreteObserver
is an implementation of the Observer
interface.main()
, we create a subject and two observers, attach the observers, set the subject's state (which notifies the observers), detach an observer, and set the state again.Using references in the Attach()
and Detach()
methods provides several benefits:
Remember, while we're using references in the interface, we're storing pointers internally. This is a common pattern when you need a mutable collection of references.
Answers to questions are automatically generated and may not have been reviewed.
This lesson demystifies references, explaining how they work, their benefits, and their role in performance and data manipulation
Comprehensive course covering advanced concepts, and how to use them on large-scale projects.
View Course