#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <set>
class Observer;
class IObserverNotifier
{
public:
virtual ~IObserverNotifier() = default;
virtual void UnRegister(Observer&) = 0;
};
class Observer
{
public:
explicit Observer() = default;
virtual ~Observer() {
for (auto* abstractObserverNotifier : mAbstractObserverNotifiers)
abstractObserverNotifier->UnRegister(*this);
}
Observer(const Observer&) = delete;
Observer(Observer&&) = delete;
Observer& operator=(const Observer&) = delete;
Observer& operator=(Observer&&) = delete;
void AddObserverNotifier(IObserverNotifier& observerNotifier)
{
mAbstractObserverNotifiers.insert(&observerNotifier);
}
void RemoveObserverNotifier(IObserverNotifier& observerNotifier)
{
mAbstractObserverNotifiers.erase(&observerNotifier);
}
private:
std::set<IObserverNotifier*> mAbstractObserverNotifiers;
};
template<typename ... Params>
class ObserverNotifier : private IObserverNotifier
{
public:
ObserverNotifier() = default;
~ObserverNotifier() {
for (const auto& p : mObserverCallbacks) {
p.first->RemoveObserverNotifier(*this);
}
}
ObserverNotifier(const ObserverNotifier&) = delete;
ObserverNotifier(ObserverNotifier&&) = delete;
ObserverNotifier& operator=(const ObserverNotifier&) = delete;
ObserverNotifier& operator=(ObserverNotifier&&) = delete;
void Register(Observer& observer, std::function<void(Params...)> f) {
mObserverCallbacks.emplace_back(&observer, f);
observer.AddObserverNotifier(*this);
}
void NotifyObservers(Params... args) const
{
for (const auto& p : mObserverCallbacks)
{
const auto& callback = p.second;
callback(args...);
}
}
private:
void UnRegister(Observer& observer) override
{
mObserverCallbacks.erase(std::remove_if(mObserverCallbacks.begin(),
mObserverCallbacks.end(),
[&](const auto& p) { return p.first == &observer;}),
mObserverCallbacks.end());
}
private:
std::vector<std::pair<Observer*, std::function<void(Params...)>>> mObserverCallbacks;
};
class Sensor
{
public:
void ChangeTime() {
++mTime;
mOnTimeChange.NotifyObservers(mTime);
}
void ChangeTemperature(double delta) {
mTemperature += delta;
mOnTemperatureChange.NotifyObservers(mTemperature);
}
void RegisterTimeChange(Observer& observer, std::function<void(double)> f) { mOnTimeChange.Register(observer, f); }
void RegisterTemperatureChange(Observer& observer, std::function<void(double)> f) { mOnTemperatureChange.Register(observer, f); }
private:
ObserverNotifier<int> mOnTimeChange;
ObserverNotifier<double> mOnTemperatureChange;
int mTime = 0;
double mTemperature = 0;
};
class Ice : public Observer {
public:
void OnTimeChanged(int time) {
mVolume -= mLose;
mOnVolumeChange.NotifyObservers(mVolume);
}
void OnTemperatureChanged(double t) {
if (t <= 0) {
mLose = 0;
} else if (t < 15) {
mLose = 5;
} else {
mLose = 21;
}
}
void RegisterVolumeChange(Observer& observer, std::function<void(double)> f) { mOnVolumeChange.Register(observer, f); }
private:
ObserverNotifier<double> mOnVolumeChange;
double mVolume = 42;
double mLose = 0;
};
class MyObserver : public Observer {
public:
static void OnTimeChange(int t) {
std::cout << "observer says time is " << t << std::endl;
}
static void OnTemperatureChange(double temperature) {
std::cout << "observer says temperature is " << temperature << std::endl;
}
static void OnIceChange(double volume) {
std::cout << "observer says Ice volume is " << volume << std::endl;
}
};
int main()
{
Sensor sensor;
Ice ice;
MyObserver observer;
sensor.RegisterTimeChange(observer, &MyObserver::OnTimeChange);
sensor.RegisterTemperatureChange(observer, &MyObserver::OnTemperatureChange);
ice.RegisterVolumeChange(observer, &MyObserver::OnIceChange);
sensor.RegisterTimeChange(ice, [&](int t){ice.OnTimeChanged(t);});
sensor.RegisterTemperatureChange(ice, [&](double t){ice.OnTemperatureChanged(t);});
sensor.ChangeTemperature(0);
sensor.ChangeTime();
sensor.ChangeTemperature(10.3);
sensor.ChangeTime();
sensor.ChangeTime();
sensor.ChangeTemperature(42.1);
sensor.ChangeTime();
}