Contesto
Esiste un'applicazione C ++ modulare. Ogni modulo fornisce un'interfaccia (una classe astratta) che viene utilizzata da altri moduli. Non ci sono dipendenze circolari. L'interazione del modulo avviene tramite chiamate al metodo diretto in un modo e tramite eventi (una variazione del pattern dell'osservatore, simile ai segnali di Qt) nell'altro modo.
Ad esempio:
// an interface towards the battery manager
class IBatteryManager
{
public:
// get the battery level
virtual int batteryLevel() = 0;
// the system is about to run out of battery and enter
// a power saving mode
virtual Event<> &aboutToRunOutOfBattery() = 0;
};
La classe Event
ha il seguente aspetto:
template<typename... tArgs>
class Event
{
public:
// client: the provided function will be called when this
// event is emitted
void subscribe(std::function<void(tArgs...)>);
// server: emit the event
void notify(tArgs...);
};
Problema e possibile soluzione
A volte un evento fire-and-forget non è abbastanza. Un modulo potrebbe voler informare i suoi clienti su alcuni eventi e attendere fino a quando non vengono elaborati (e magari recuperare alcuni valori).
Ad esempio, BatteryManager
potrebbe voler attendere che tutti i client abbiano elaborato l'evento circa l'esaurimento della batteria prima di accedere alla modalità di risparmio energetico.
Posso immaginare più modi in cui ciò può essere fatto. Uno di questi sarebbe quello di estendere la classe Event
con lo schema futuro / promesso nel seguente modo:
template<typename tValue, typename... tArgs>
class Event
{
public:
// client: now must return some value
void subscribe(std::function<Future<tValue>(tArgs...)>);
// server: this future is fulfilled as soon as all clients
// have completed their promises
Future<std::vector<tValue>> notify(tArgs...);
};
Domande
Aggiornato: ho riformulato alcune domande per essere più chiaro.
Esiste un modello di progettazione che descrive l'approccio mostrato sopra? In altre parole, tale approccio ha un nome comunemente accettato, un vocabolario, pro / contro, un'implementazione canonica, una lista di cose alle quali bisogna prestare attenzione e altre cose quali sono i modelli di solito?
Sto chiedendo perché questo potrebbe non essere un problema che è unico per me. Quindi non voglio finire per reinventare la ruota, sia in termini di implementazione (probabilmente rifacendo gli errori di qualcun altro) che di terminologia (introducendo i miei termini, che renderanno più difficile la comunicazione con gli altri sviluppatori).
Domande secondarie: ci sono forse approcci migliori? Quale sarebbe la migliore pratica in questo caso?