This commit is contained in:
Alexander Zhirov 2021-11-01 11:54:58 +03:00
parent 3b15979dfe
commit 168db11957
11 changed files with 366 additions and 0 deletions

View File

@ -0,0 +1,6 @@
Паттерн "Наблюдатель" определяет отношение "один-ко-многим" между объектами таким образом, что при изменении состояния одного объекта происходит автоматическое оповещение и обновление всех зависимых объектов.
При использовании паттерна возможен как запрос, так и активная доставка данных от субъекта (запрос считается более "правильным").
*Принцип:*
- Слабосвязанные структуры более гибки и лучше выдерживают изменения.

View File

@ -0,0 +1,38 @@
/*
* CurrentConditionsDisplay.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
#include "Observer.hpp"
#include "DisplayElement.hpp"
#include "WeatherData.hpp"
class CurrentConditionsDisplay: public Observer, public DisplayElement
{
private:
float temperature;
float humidity;
WeatherData &weatherData;
public:
CurrentConditionsDisplay(WeatherData &weatherData) :
temperature(0.0), humidity(0.0), weatherData(weatherData)
{
weatherData.registerObserver(*this);
}
void update(float temperature, float humidity, float pressure) override
{
this->temperature = temperature;
this->humidity = humidity;
display();
}
void display() const override
{
std::cout << "Current conditions: " << temperature << "F degrees and " << humidity << "% humidity" << std::endl;
}
};

View File

@ -0,0 +1,16 @@
/*
* DisplayElement.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
class DisplayElement
{
public:
virtual void display() const = 0;
virtual ~DisplayElement() {}
};

View File

@ -0,0 +1,47 @@
/*
* ForecastDisplay.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
#include "Observer.hpp"
#include "DisplayElement.hpp"
#include "WeatherData.hpp"
class ForecastDisplay: public Observer, public DisplayElement
{
private:
float currentPressure;
float lastPressure;
WeatherData &weatherData;
public:
ForecastDisplay(WeatherData &weatherData) :
currentPressure(29.92), lastPressure(0.0), weatherData(weatherData)
{
weatherData.registerObserver(*this);
}
void update(float temperature, float humidity, float pressure) override
{
this->lastPressure = this->currentPressure;
this->currentPressure = pressure;
display();
}
void display() const override
{
std::cout << "Forecast: ";
if (currentPressure > lastPressure) {
std::cout << "Improving weather on the way!";
} else if (currentPressure == lastPressure) {
std::cout << "More of the same";
} else if (currentPressure < lastPressure) {
std::cout << "Watch out for cooler, rainy weather";
}
std::cout << std::endl;
}
};

View File

@ -0,0 +1,46 @@
/*
* HeatIndexDisplay.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
#include "Observer.hpp"
#include "DisplayElement.hpp"
#include "WeatherData.hpp"
class HeatIndexDisplay: public Observer, public DisplayElement
{
private:
float heatIndex;
WeatherData &weatherData;
float computeHeatIndex(float t, float rh)
{
float index = (float) ((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh))
+ (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t))
+ (0.0000291583 * (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh))
- (0.0000000218429 * (t * t * t * rh * rh)) + 0.000000000843296 * (t * t * rh * rh * rh))
- (0.0000000000481975 * (t * t * t * rh * rh * rh)));
return index;
}
public:
HeatIndexDisplay(WeatherData &weatherData) : heatIndex(0.0), weatherData(weatherData)
{
weatherData.registerObserver(*this);
}
void update(float temperature, float humidity, float pressure) override
{
heatIndex = computeHeatIndex(temperature, humidity);
display();
}
void display() const override
{
std::cout << "Heat index is " << heatIndex << std::endl;
}
};

16
lesson_2/Observer.hpp Normal file
View File

@ -0,0 +1,16 @@
/*
* Observer.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
class Observer
{
public:
virtual void update(float temp, float humidity, float pressure) = 0;
virtual ~Observer() {}
};

View File

@ -0,0 +1,48 @@
/*
* StaticDisplay.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#include "Observer.hpp"
#include "DisplayElement.hpp"
#include "WeatherData.hpp"
class StaticDisplay: public Observer, public DisplayElement
{
private:
float maxTemp;
float minTemp;
float tempSum;
int numReadings;
WeatherData &weatherData;
public:
StaticDisplay(WeatherData &weatherData) :
maxTemp(0.0), minTemp(200.0), tempSum(0.0), numReadings(0), weatherData(weatherData)
{
weatherData.registerObserver(*this);
}
void update(float temperature, float humidity, float pressure) override
{
this->tempSum += temperature;
this->numReadings++;
if (temperature > this->maxTemp) {
this->maxTemp = temperature;
}
if (temperature < this->minTemp) {
this->minTemp = temperature;
}
display();
}
void display() const override
{
std::cout << "Avg/Max/Min temperature = " << (tempSum / numReadings)
<< "/" << maxTemp << "/" << minTemp << std::endl;
}
};

20
lesson_2/Subject.hpp Normal file
View File

@ -0,0 +1,20 @@
/*
* Subject.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
#include "Observer.hpp"
class Subject
{
public:
virtual void registerObserver(Observer &o) = 0;
virtual void removeObserver(Observer &o) = 0;
virtual void notifyObservers() = 0;
virtual ~Subject() {}
};

72
lesson_2/WeatherData.hpp Normal file
View File

@ -0,0 +1,72 @@
/*
* WeatherData.hpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#pragma once
#include "Subject.hpp"
#include <list>
#include <functional>
#include <iostream>
class WeatherData: public Subject
{
private:
std::list<std::reference_wrapper<Observer>> observers;
float temperature;
float humidity;
float pressure;
public:
void registerObserver(Observer &o) override
{
observers.push_back(o);
}
void removeObserver(Observer &o) override
{
observers.erase(std::find_if(observers.cbegin(), observers.cend(), [&](const std::reference_wrapper<Observer> &item)
{
return &item.get() == &o;
}));
std::cout << "Осталось в листе: " << observers.size() << " элементов" << std::endl;
}
void notifyObservers() override
{
for (Observer &observer : observers)
{
observer.update(temperature, humidity, pressure);
}
}
void measurementsChanged()
{
notifyObservers();
}
void setMeasurements(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
measurementsChanged();
}
float getTemperature()
{
return temperature;
}
float getHumidity()
{
return humidity;
}
float getPressure()
{
return pressure;
}
};

28
lesson_2/main.cpp Normal file
View File

@ -0,0 +1,28 @@
/*
* main.cpp
*
* Created on: 31 окт. 2021 г.
* Author: alexander
*/
#include "WeatherData.hpp"
#include "CurrentConditionsDisplay.hpp"
#include "StaticDisplay.hpp"
#include "ForecastDisplay.hpp"
#include "HeatIndexDisplay.hpp"
int main()
{
WeatherData weatherData;
CurrentConditionsDisplay currentDisplay(weatherData);
StaticDisplay staticDisplay(weatherData);
ForecastDisplay forecastDisplay(weatherData);
HeatIndexDisplay heatIndexDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
return 0;
}

29
lesson_2/scheme Normal file
View File

@ -0,0 +1,29 @@
// interface
class Subject
{
public:
virtual void registerObserver() = 0;
virtual void removeObserver() = 0;
virtual void notifyObserver() = 0;
};
class Observer
{
public:
virtual void update() = 0;
};
// classes
class ConcreteSubject : public Subject
{
public:
void getState();
void setState();
};
class ConcreteObserver : public Observer
{
public:
};