Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Alexander Zhirov | 168db11957 |
|
@ -0,0 +1,6 @@
|
|||
Паттерн "Наблюдатель" определяет отношение "один-ко-многим" между объектами таким образом, что при изменении состояния одного объекта происходит автоматическое оповещение и обновление всех зависимых объектов.
|
||||
|
||||
При использовании паттерна возможен как запрос, так и активная доставка данных от субъекта (запрос считается более "правильным").
|
||||
|
||||
*Принцип:*
|
||||
- Слабосвязанные структуры более гибки и лучше выдерживают изменения.
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* DisplayElement.hpp
|
||||
*
|
||||
* Created on: 31 окт. 2021 г.
|
||||
* Author: alexander
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class DisplayElement
|
||||
{
|
||||
public:
|
||||
virtual void display() const = 0;
|
||||
|
||||
virtual ~DisplayElement() {}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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() {}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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() {}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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:
|
||||
};
|
Reference in New Issue