Observer Pattern

inserting an Image

Keywords

Observable

  • Is the interface or abstract class which defines the operations for attaching and de-attaching observers to the client.

Concerete Observable

  • Maintains the state of the object and when a change occurs it notifies the attached Obersvers

Observer

  • Is the interface of abstract class defining the operation to be used to modify the obkect

Concrete Observer(s)

  • Implementations of Observers

Weather Station Example

Observer Header (Observer.h)

  • The Observer is the parent class of the concrete observers (cell phone clients in our case), it contains
#ifndef OBSERVER_PATTERN
#define OBSERVER_PATTERN

/**
 * Interface for the Observer
 */
class Observer {

public:

    virtual void update(float temp, float humidity, float pressure, float wind) = 0; // Virtual Function

};

#endif 

Subject Header (Subject.h)


#ifndef OBSERVER_PATTERN_SUBJECT_H
#define OBSERVER_PATTERN_SUBJECT_H


#include "Observer.h"

/**
 * Interface for the Subject
 */
class Subject {

public:

    virtual void registerObserver(Observer *observer) = 0;

    virtual void removeObserver(Observer *observer) = 0;

    virtual void notifyObservers() = 0;

};

#endif 

Weather Data Header (WeatherData.h)

#ifndef OBSERVER_PATTERN_WEATHERDATA_H
#define OBSERVER_PATTERN_WEATHERDATA_H

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

#include "Subject.h"
#include "Observer.h"

/**
 * A concrete implementation of the Subject interface
 */
class WeatherData : public Subject {

private:
    std::vector<Observer *> observers; // observers need a list of them so we can update

    float temp = 0.0f;
    float humidity = 0.0f;
    float pressure = 0.0f;
    float wind = 0.0f;

public:

    void registerObserver(Observer *observer) override;

    void removeObserver(Observer *observer) override;

    void notifyObservers() override;

    void setState(float temp, float humidity, float pressure, float wind);

};

#endif

Weather Data (WeatherData.cpp)

#include "WeatherData.h"

void WeatherData::registerObserver(Observer *observer) {
    // Adds new observer to vector
    observers.push_back(observer);
}

void WeatherData::removeObserver(Observer *observer) {
    // find the observer and remove it 
    auto iterator = std::find(observers.begin(), observers.end(), observer);

    if (iterator != observers.end()) { // observer found
        observers.erase(iterator); // remove the observer
    }
}

void WeatherData::notifyObservers() {
    for (Observer *observer : observers) { // notify all observers
        observer->update(temp, humidity, pressure, wind);
    }
}

void WeatherData::setState(float temp, float humidity, float pressure, float wind) {
    this->temp = temp;
    this->humidity = humidity;
    this->pressure = pressure;
    this->wind = wind;
    std::cout << std::endl;
    notifyObservers();
}

Client Header (Client.h)

#ifndef OBSERVER_PATTERN_CLIENT_1_H
#define OBSERVER_PATTERN_CLIENT_1_H

#include <iostream>

#include "Observer.h"

/**
 * a client that implements the Observer interface
 */
class Client : public Observer {

private:

    int id; // Label the Identification number of the Client

public:

    Client(int id);

    virtual void update(float temp, float humidity, float pressure, float wind) override;

};

#endif

Client (Client.cpp)

#include "Client.h"

void Client::update(float temp, float humidity, float pressure, float {
    // print the changed values
    std::cout << "---Client (" << id << ") Data---\tTemperature: " << temp
              << "\tHumidity: " << humidity
              << "\tPressure: " << pressure
              << "\tWind Speed (mph): " << wind 
              << std::endl;
}

Client::Client(int id) {
    // Set Client id
    this->id = id;
}

Main File (main.cpp)

#include <iostream>
#include "WeatherData.h"
#include "Client.h"


int main() {
    WeatherData weatherStation;
    Client one(1), two(2), three(3), four(4), five(5);

    float temp, humidity, pressure;

    weatherStation.registerObserver(&one);
    weatherStation.registerObserver(&two);
    weatherStation.registerObserver(&three);
    weatherStation.registerObserver(&four);
    weatherStation.registerObserver(&five);


    std::cout << "Enter Temperature, Humidity, Pressure (seperated by spaces) << ";
    std::cin >> temp >> humidity >> pressure;

    weatherStation.setState(temp,humidity,pressure);

    weatherStation.removeObserver(&two); // Remove from 

    std::cout << "\n\nEnter Temperature, Humidity, Pressure (seperated by spaces) << ";
    std::cin >> temp >> humidity >> pressure;

    weatherStation.setState(temp,humidity,pressure);

}

Output:

Enter Temperature, Humidity, Pressure (seperated by spaces) << 90 98.3 45

---Client (1) Data---   Temperature: 90 Humidity: 98.3  Pressure: 45
---Client (2) Data---   Temperature: 90 Humidity: 98.3  Pressure: 45
---Client (3) Data---   Temperature: 90 Humidity: 98.3  Pressure: 45
---Client (4) Data---   Temperature: 90 Humidity: 98.3  Pressure: 45
---Client (5) Data---   Temperature: 90 Humidity: 98.3  Pressure: 45


Enter Temperature, Humidity, Pressure (seperated by spaces) << 92 94.4 67

---Client (1) Data---   Temperature: 92 Humidity: 94.4  Pressure: 67
---Client (3) Data---   Temperature: 92 Humidity: 94.4  Pressure: 67
---Client (4) Data---   Temperature: 92 Humidity: 94.4  Pressure: 67