Implementing Observer Pattern with References

How can I use references to implement a simple observer pattern in C++?

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:

  1. We define an Observer interface with a pure virtual Update() method.
  2. The Subject class maintains a list of observer pointers. We use pointers here because std::vector can't store references directly.
  3. The 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.
  4. When SetState() is called, it updates the state and calls Notify(), which updates all observers.
  5. ConcreteObserver is an implementation of the Observer interface.
  6. In 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:

  • It's more intuitive: passing by reference clearly communicates that we're working with an existing object.
  • It's safer: you can't pass a null reference, unlike with pointers.
  • It's efficient: no need to check for null before dereferencing.

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.

References

This lesson introduces references, explaining how they work, their benefits, and their role in performance and data manipulation

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Swapping Values Using References
How can I use references to swap the values of two variables without using a temporary variable?
Creating an Array of References
Is it possible to create an array of references in C++?
References and Runtime Polymorphism
Can I use references with polymorphic classes to achieve runtime polymorphism?
Reference vs Pointer to Const
What's the difference between a reference and a pointer to const in terms of function parameters?
Dangers of Returning References to Local Objects
What are the implications of returning a reference from a function that creates a local object?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant