IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Quel système d'abonnement ?


Sujet :

C++

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut Quel système d'abonnement ?
    Bonjour à tous,

    Supposons que je code une API de ce type :

    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();
    }
    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
    // 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 : 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;
    }
    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).

  2. #2
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Et si tu utilisais std::shared_ptr, potentiellement en combinaison de std::weak_ptr? mal lu la contrainte

    De toutes facons ton systeme ne marchera jamais correctement sans une forme de smart pointer. Toutes les alternatives sont a la fois intrusives et visible par l'utilisateur.

    Au pire fait toi ton propre smart pointer mais franchement c'est pas evident.

    Une alternative a ton systeme, mais dont l'interet depends totalement de si tu as vraiment besoin de pointeurs dans ton service, c'est de passer par un simple id de resource au lieu d'un pointeur.

    Comme ca ton service doit toujours recuperer l'objet quand il en a besoin et l'utiliser seulement si il est trouve.

    Cela dis, les deux aproches que tu as sont pour moi completement unsafe en tout cas si c'est du multithread

Discussions similaires

  1. [Templates] Quel système utilisez-vous ? Pourquoi ?
    Par narmataru dans le forum Bibliothèques et frameworks
    Réponses: 270
    Dernier message: 26/03/2011, 00h15
  2. Quel système utiliser : GUI ou web ?
    Par MaTHieU_ dans le forum Débats sur le développement - Le Best Of
    Réponses: 54
    Dernier message: 07/05/2007, 07h13
  3. Réponses: 10
    Dernier message: 16/04/2007, 17h45
  4. [SGBD] Quel système pour le net ?
    Par Invité dans le forum Windows Forms
    Réponses: 5
    Dernier message: 26/03/2007, 15h33
  5. Quel système de construction de projets utiliser ?
    Par YéTeeh dans le forum Choisir un environnement de développement
    Réponses: 3
    Dernier message: 11/07/2006, 14h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo