A very common pattern for a codebase is a Listener
affair like this:
class Frobulator
{
public:
class Listener
{
private:
// only frobulators can frob
friend class Frobulator;
virtual void onFrobbed() = 0;
}
void maybeFrob()
{
// assume we always frob, but maybe we only do it sometimes
// and the caller won't know if a call will do it
for (auto& l: listeners)
{
l->onFrobbed();
}
}
void addListener(Listener* l)
{
listeners.push_back(l);
}
private:
std::vector<Listener*> listeners;
}
Then, a class inherits Listener
and can register as a listener with the Frobulator
. When the Frobulator
frobs after a call by some caller (not necessarily the listener), the listeners will be told.
The real question I have then is, should the listener listen "internally", and therefore need a non-const reference to the Frobulator
, but manage with a private
Listener
nature?
class FrobReactor: private Frobulator::Listener
{
public:
FrobReactor(Frobulator& frobulator_)
frobulator(frobulator)
{
frobulator.addListener(this);
}
private:
void onFrobbed() override
{
// react!
}
Frobulator& frobulator;
}
// and externally ...
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.maybeFrob();
Or should the listener take a const-reference (or even no reference if you don't need it), acknowledging that the FrobReactor
doesn't modify the Frobulator
, but advertising that it is a Frobulator::Listener
and expecting the client code to hook it up:
class FrobReactor: public Frobulator::Listener
{
public:
FrobReactor(const Frobulator& frobulator_):
frobulator(frobulator_)
{
}
private:
void onFrobbed() override
{
// react!
}
const Frobulator& frobulator;
}
// and externally
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.addListener(&reactor);
theFrobber.maybeFrob();
Alternatively the addListener
method could be made const and the listener list mutable
and then the first method also works with a non-const reference, but this feels like a hack.
Is there a "right" way to do this?
Aucun commentaire:
Enregistrer un commentaire