diff --git a/README.md b/README.md index e69de29..b20d7f7 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,6 @@ +Паттерн "Наблюдатель" определяет отношение "один-ко-многим" между объектами таким образом, что при изменении состояния одного объекта происходит автоматическое оповещение и обновление всех зависимых объектов. + +При использовании паттерна возможен как запрос, так и активная доставка данных от субъекта (запрос считается более "правильным"). + +*Принцип:* +- Слабосвязанные структуры более гибки и лучше выдерживают изменения. diff --git a/lesson_2/CurrentConditionsDisplay.hpp b/lesson_2/CurrentConditionsDisplay.hpp new file mode 100644 index 0000000..409ae92 --- /dev/null +++ b/lesson_2/CurrentConditionsDisplay.hpp @@ -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; + } +}; diff --git a/lesson_2/DisplayElement.hpp b/lesson_2/DisplayElement.hpp new file mode 100644 index 0000000..9d4b42a --- /dev/null +++ b/lesson_2/DisplayElement.hpp @@ -0,0 +1,16 @@ +/* + * DisplayElement.hpp + * + * Created on: 31 окт. 2021 г. + * Author: alexander + */ + +#pragma once + +class DisplayElement +{ +public: + virtual void display() const = 0; + + virtual ~DisplayElement() {} +}; diff --git a/lesson_2/ForecastDisplay.hpp b/lesson_2/ForecastDisplay.hpp new file mode 100644 index 0000000..e06f9fe --- /dev/null +++ b/lesson_2/ForecastDisplay.hpp @@ -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; + } +}; diff --git a/lesson_2/HeatIndexDisplay.hpp b/lesson_2/HeatIndexDisplay.hpp new file mode 100644 index 0000000..ec5161a --- /dev/null +++ b/lesson_2/HeatIndexDisplay.hpp @@ -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; + } +}; diff --git a/lesson_2/Observer.hpp b/lesson_2/Observer.hpp new file mode 100644 index 0000000..6cb8b99 --- /dev/null +++ b/lesson_2/Observer.hpp @@ -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() {} +}; diff --git a/lesson_2/StaticDisplay.hpp b/lesson_2/StaticDisplay.hpp new file mode 100644 index 0000000..15143c2 --- /dev/null +++ b/lesson_2/StaticDisplay.hpp @@ -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; + } +}; diff --git a/lesson_2/Subject.hpp b/lesson_2/Subject.hpp new file mode 100644 index 0000000..eb0e8ce --- /dev/null +++ b/lesson_2/Subject.hpp @@ -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() {} +}; diff --git a/lesson_2/WeatherData.hpp b/lesson_2/WeatherData.hpp new file mode 100644 index 0000000..6daa272 --- /dev/null +++ b/lesson_2/WeatherData.hpp @@ -0,0 +1,72 @@ +/* + * WeatherData.hpp + * + * Created on: 31 окт. 2021 г. + * Author: alexander + */ + +#pragma once + +#include "Subject.hpp" +#include +#include +#include + +class WeatherData: public Subject +{ +private: + std::list> 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 &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; + } +}; diff --git a/lesson_2/main.cpp b/lesson_2/main.cpp new file mode 100644 index 0000000..29fa94a --- /dev/null +++ b/lesson_2/main.cpp @@ -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; +} + diff --git a/lesson_2/scheme b/lesson_2/scheme new file mode 100644 index 0000000..fbaebdb --- /dev/null +++ b/lesson_2/scheme @@ -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: +};