Menu
Coddy logo textTech

Modèle Observer

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 94 sur 104.

Le pattern Observer définit une dépendance de type un-à-plusieurs entre les objets : lorsqu’un objet (le sujet) change d’état, tous ses dépendants (les observateurs) sont automatiquement avertis. Cela convient parfaitement aux systèmes d’événements, aux mises à jour de l’interface utilisateur ou à tout scénario dans lequel plusieurs objets doivent réagir aux changements.

Le modèle implique deux rôles clés : un Sujet qui gère une liste d’observateurs et les informe, et des Observateurs qui implémentent une interface de mise à jour :

#include <iostream>
#include <vector>
#include <algorithm>

class Observer {
public:
    virtual void update(int value) = 0;
    virtual ~Observer() = default;
};

class Subject {
    std::vector<Observer*> observers;
    int state = 0;
    
public:
    void attach(Observer* obs) {
        observers.push_back(obs);
    }
    
    void detach(Observer* obs) {
        observers.erase(
            std::remove(observers.begin(), observers.end(), obs),
            observers.end());
    }
    
    void setState(int value) {
        state = value;
        notify();
    }
    
    void notify() {
        for (Observer* obs : observers) {
            obs->update(state);
        }
    }
};

class Display : public Observer {
    std::string name;
public:
    Display(const std::string& n) : name(n) {}
    void update(int value) override {
        std::cout << name << " received: " << value << "\n";
    }
};

int main() {
    Subject sensor;
    Display screen1("Screen1"), screen2("Screen2");
    
    sensor.attach(&screen1);
    sensor.attach(&screen2);
    sensor.setState(42);  // Les deux affichages notifiés
}

Lorsque setState() est appelée, le sujet parcourt tous les observateurs enregistrés et appelle leur méthode update(). Les observateurs peuvent s’attacher ou se détacher à tout moment, ce qui rend le système flexible et faiblement couplé.

Utilisez Observer lorsque des modifications apportées à un objet nécessitent la mise à jour d’autres objets et que vous ne voulez pas que ces objets soient fortement couplés.

challenge icon

Défi

Facile

Construisons un système de surveillance de station météo utilisant le modèle Observer. Vous allez créer une station météo qui suit les données de température et avertit automatiquement plusieurs unités d’affichage chaque fois que la température change : une application classique de ce modèle dans le monde réel.

Vous organiserez votre code sur trois fichiers :

  • Observer.h : définir l’interface de l’observateur et un observateur d’affichage concret.

    Créez une classe abstraite Observer avec une méthode virtuelle pure update(double temperature) que les observateurs implémentent pour recevoir les notifications, ainsi qu’un destructeur virtuel.

    Créez ensuite une classe TemperatureDisplay qui hérite de Observer. Chaque affichage possède un nom (chaîne de caractères) défini par son constructeur. Lorsque update() est appelée, elle doit afficher :

    [DisplayName]: Temperature is [temperature] degrees
  • WeatherStation.h : créer le sujet qui conserve la température et avertit les observateurs.

    Votre classe WeatherStation doit :

    • Stocker une liste de pointeurs vers les observateurs ainsi que la température actuelle (initialisée à 0.0)
    • Posséder une méthode attach(Observer* obs) pour enregistrer des observateurs
    • Posséder une méthode detach(Observer* obs) pour supprimer des observateurs
    • Posséder une méthode setTemperature(double temp) qui met à jour la température et avertit tous les observateurs associés
    • Posséder une méthode privée notify() qui appelle update() sur chaque observateur avec la température actuelle
  • main.cpp : démontrer le fonctionnement du modèle Observer.

    Lisez trois entrées :

    1. Nom du premier affichage (chaîne de caractères)
    2. Nom du deuxième affichage (chaîne de caractères)
    3. Une valeur de température (double)

    Créez une WeatherStation et deux objets TemperatureDisplay avec les noms fournis. Associez les deux affichages à la station, puis définissez la température sur la valeur saisie. Les deux affichages doivent automatiquement recevoir la mise à jour et afficher leurs messages.

    Ensuite, détachez le premier affichage et définissez une nouvelle température supérieure de 5 degrés à la valeur saisie. Seul le deuxième affichage doit recevoir cette mise à jour.

Par exemple, avec les entrées Kitchen, Bedroom et 22.5 :

Kitchen: Temperature is 22.5 degrees
Bedroom: Temperature is 22.5 degrees
Bedroom: Temperature is 27.5 degrees

Avec les entrées Office, Lobby et 18.0 :

Office: Temperature is 18 degrees
Lobby: Temperature is 18 degrees
Lobby: Temperature is 23 degrees

Remarquez comment le modèle Observer crée un système faiblement couplé : la station météo n’a pas besoin de connaître les affichages spécifiques, elle avertit simplement toute personne à l’écoute. Lorsque vous détachez un observateur, celui-ci cesse automatiquement de recevoir les mises à jour.

Essayez vous-même

#include <iostream>
#include <string>
#include "WeatherStation.h"

using namespace std;

int main() {
    // Lire les entrées
    string display1Name, display2Name;
    double temperature;
    
    cin >> display1Name;
    cin >> display2Name;
    cin >> temperature;
    
    // TODO: Créer un objet WeatherStation
    
    // TODO: Créer deux objets TemperatureDisplay avec les noms d'entrée
    
    // TODO: Attacher les deux affichages à la station météo
    
    // TODO: Définir la température à la valeur d'entrée
    // (Les deux affichages doivent imprimer leurs messages)
    
    // TODO: Détacher le premier affichage
    
    // TODO: Définir la température à 5 degrés de plus que l'entrée
    // (Seul le second affichage doit imprimer)
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne