// Hello world! Cplayground is an online sandbox that makes it easy to try out
// code.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <set>
template<typename T>
class Subject;
template<typename T>
class Observer
{
std::set<Subject<T>*> _subjects;
public:
virtual void update(T val) = 0;
void addSubject(Subject<T>* subject)
{
printf ("[Observer] Adding Subject to observer - ");
_subjects.insert(subject);
std::cout << "Subject size = " << _subjects.size() << "\n\n";
}
void removeSubject(Subject<T>* subject)
{
printf ("[Observer] Removing Subject from observer - ");
_subjects.erase(subject);
std::cout << "Subject size = " << _subjects.size() << "\n";
}
virtual ~Observer()
{
printf ("\n~Observer\nSubject Size = %ld\n", _subjects.size());
for (auto& subject : _subjects)
{
subject->detach(this);
}
}
};
template<typename T>
class Subject
{
std::set<Observer<T>*> _observers;
protected:
Subject() = default;
public:
void attach(Observer<T>* observer)
{
printf ("~~ [Subject] Attaching observer ~~\n");
_observers.insert(observer);
observer->addSubject(this);
}
void detach(Observer<T>* observer)
{
printf ("~~ [Subject] Detaching observer ~~\n");
std::cout << "Observers size = " << _observers.size() << "\n";
_observers.erase(observer);
observer->removeSubject(this);
}
void notify(const T& val)
{
for (auto& observer : _observers)
{
observer->update(val);
}
}
virtual ~Subject()
{
printf ("\n~Subject\n");
printf ("Observer size = %ld\n", _observers.size());
for (auto& obs : _observers)
{
obs->removeSubject(this);
}
}
};
template<typename T>
class ConcreteSubject : public Subject<T>
{
T _value;
public:
void set(const T& value)
{
_value = value;
this->notify(value);
}
};
template<typename T>
class ConcreteObserver : public Observer<T>
{
public:
void update(T value)
{
std::cout << "Observer Notified: " << value << "\n";
}
};
int main()
{
ConcreteSubject<int> sub;
{
ConcreteObserver<int> obs;
ConcreteObserver<int> obs1;
sub.attach(&obs);
sub.attach(&obs1);
sub.set(5);
printf ("\n-------- Observers going out of scope -----------\n");
}
printf ("...finishing main...\n");
return 0;
}