Bonjour à tous,
Supposons que je code une API de ce type :
Utilisée de cette manière :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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(); }
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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);
Pour l'instant je procède ainsi, ServiceImpl et ServiceResourceImpl étant les deux classes concrètes implémentant mon API :
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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; }
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).
Partager