Solution: Observer¶
#pragma once
#include <socialdb.h>
#include <set>
class SocialDB_Observable : public SocialDB
{
public:
class ObserverAlreadyRegistered : public std::exception
{
public:
virtual const char* what() const noexcept { return "Observer already registered"; }
};
class ObserverNotRegistered : public std::exception
{
public:
virtual const char* what() const noexcept { return "Observer not registered"; }
};
public:
class NewCitizenObserver
{
public:
virtual ~NewCitizenObserver() {}
virtual void new_citizen_added(const std::string& svnr) = 0;
};
public:
void insert(const std::string& svnr, const std::string& firstname, const std::string& lastname);
void register_new_citizen_notification(NewCitizenObserver*);
void unregister_new_citizen_notification(NewCitizenObserver*);
private:
std::set<NewCitizenObserver*> _new_citizen_observers;
};
#include "social-db-observable.h"
void SocialDB_Observable::insert(
const std::string& svnr,
const std::string& firstname,
const std::string& lastname)
{
SocialDB::insert(svnr, firstname, lastname);
for (auto observer: _new_citizen_observers)
observer->new_citizen_added(svnr);
}
void SocialDB_Observable::register_new_citizen_notification(
NewCitizenObserver* o)
{
if (_new_citizen_observers.find(o) != _new_citizen_observers.end())
throw ObserverAlreadyRegistered();
_new_citizen_observers.insert(o);
}
void SocialDB_Observable::unregister_new_citizen_notification(
NewCitizenObserver* o)
{
auto num_erased = _new_citizen_observers.erase(o);
if (num_erased == 0)
throw ObserverNotRegistered();
}