Quel système d'abonnement ?
Bonjour à tous,
Supposons que je code une API de ce type :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| //classe abstraite
class ServiceResource {
static ServiceResource* Create();
static void Destroy(ServiceResource* res);
protected:
~ServiceResource();
}
//classe abstraite
class Service {
static Service* Create();
static void Destroy(Service* res);
virtual void connect(ServiceResource* res) = 0;
protected:
~Service();
} |
Utilisée de cette manière :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| // Allocation
Service* srv = Service::Create();
ServiceResource* res = ServiceResource::Create();
// Acquisition de la ressource par le service
srv->connect(res);
// Utilisation du service
...
// Désalloc
ServiceResource::Destroy(res);
Service::Destroy(srv); |
J'aimerais qu'à l'appel de ServiceResource::Destroy(res), l'objet srv qui utilise cette ressource s'en "désabonne", par un système de callbacks ou autre.
Pour l'instant je procède ainsi, ServiceImpl et ServiceResourceImpl étant les deux classes concrètes implémentant mon API :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
void ServiceImpl::connect(ServiceResource* res) {
ServiceResourceImpl* resimpl = dynamic_cast<ServiceResourceImpl*>(res);
if (resimpl != nullptr) {
// Pour que la ressource sache quel service l'utilise, et puisse notifier le service pour qu'il s'en désabonne si la ressource est détruite
// (nb: idéalement il faudrait remplir un pool de services, pour gérer le cas d'abonnements multiples à une ressource, mais passons)
resimpl->setService(this);
}
this->resource = res;
}
void ServiceResource::Destroy(ServiceResource* res) {
ServiceResourceImpl* resimpl = dynamic_cast<ServiceResourceImpl*>(res);
if (resimpl != nullptr) {
// "nullptr" pour que le service comprenne qu'il n'est plus connecté à aucune ressource.
resimpl->getService()->connect(nullptr);
}
delete res;
} |
Mes classes concrètes disposent donc de pointeurs en attributs (et des get/set associés) pour se désigner l'un l'autre, de manière à ce que le service connaisse l'adresse de la ressource et inversement.
Mais comme vous avez pu le remarquer, j'utilise des dynamic_cast, donc RTTI, ce que j'aimerais éviter. Connaissez-vous une solution alternative, un design pattern que j'aurais manqué ?
Contraintes :
- Pas de types STD/BOOST dans le header de mon API ; en fait je n'y inclus rien.
- Si possible, ne pas trop polluer les classes de l'API. L'abonnement doit être transparent pour l'utilisateur (quoique, si vous avez un avis différent sur ce dernier point, je vous écoute).