lesson_2
This commit is contained in:
parent
3b15979dfe
commit
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