Observer Pattern
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