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 :

Problème de conception : patron "fabrique" ?


Sujet :

C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Problème de conception : patron "fabrique" ?
    Hello,

    En fonction du type d'un objet donné, je dois créer un autre objet d'un type donné. Il n'y a pas nécessairement une relation d'héritage entre les divers types.

    Exemple :
    Si j'ai un objet de type "Mary", je dois créer un objet du type "Poppins".

    Je dispose du type de l'objet en question (fourni par une fonction membre), sous forme de chaîne, et peut donc l'envoyer en paramètre à une fonction.

    1 - Une variante du patron "fabrique" est-elle adaptée à cela ? Je crois savoir que le concept de la fabrique repose sur des relations d'héritage entre les types.

    2 - Accessoirement, est-il possible de faire statiquement l'association ?

    Je précise que je n'ai encore jamais mis le nez dans les design patterns..

    J'ai été voir cette page de Developpez.com, mais elle ne correspond pas tout à fait à mes besoins (clones, etc.)

    Des petites idées ?

    J'ai actuellement le nez dans le bouquin Design Pattern, et mon besoin se rapprocherait azssez de la "fabrique paramétrisée", sauf que je veux éviter les "if" en cascade (j'ai des dizaines de types à gérer).

    J'ai l'impression que je ferais mieux de passer par un map [type]/[pointeur de fonction]. Dans ce cas, j'aimerais bien initialiser ce map de manière statique.

    Merci !

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    1- tu veux dire que tous les objets que tu veux pouvoir fabriquer ne dérivent pas d'un type commun ?
    Soit tu définis une fabrique par hiérarchie de types liées
    Soit tu renvoies un pointeur vers un boost::any ou autre type variant.

    2- Tu ne pourras pas faire d'association statique, efficace (i.e. en O(1)), entre une chaine de caractères et un objet à fabriquer.
    Avec des IDs, tu peux figer un truc non ouvert (cf principe open-close) à coups de switchs. Ou alors avec des types (ou des IDs) on s'en sort par méta-prog template ; mais alors quel intérêt à faire une fabrique ?


    Bref, montre nous le code utilisateur que tu aimerais écrire, on te dira comment y arriver -- si c'est possible.

    PS: dernièrement (pas plus d'un mois et demi), la question des fabriques est revenue dans le forum C&C++/Contribuez. D'autres solutions ont été évoquées.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    1- tu veux dire que tous les objets que tu veux pouvoir fabriquer ne dérivent pas d'un type commun ?
    Soit tu définis une fabrique par hiérarchie de types liées
    Soit tu renvoies un pointeur vers un boost::any ou autre type variant.
    Je peux faire en sorte qu'ils dérivent d'un type commun. Mais l'emploi du polymorphisme s'effectuera à un niveau intermédiaire.
    Mais ce n'est pas tant là que réside mon problème (même si je note ton observation, car il n'est pas exclu que le problème se présentera à moi par la suite).

    2- Tu ne pourras pas faire d'association statique, efficace (i.e. en O(1)), entre une chaine de caractères et un objet à fabriquer.
    Avec des IDs, tu peux figer un truc non ouvert (cf principe open-close) à coups de switchs. Ou alors avec des types (ou des IDs) on s'en sort par méta-prog template; mais alors quel intérêt à faire une fabrique ?
    J'aimerais justement éviter les switch / if en cascade, car il y a beaucoup de types. Pour l'open/close, ce n'est pas gênant, car l'utilisation est interne à la classe.

    Citation Envoyé par Luc Hermitte Voir le message
    Bref, montre nous le code utilisateur que tu aimerais écrire, on te dira comment y arriver -- si c'est possible.
    J'espère que tu comprendras ce que je veux avec ce qui figure ci-dessous.
    J'ai mis en italique les choses que je sais incorrectes, mais qui aident à exprimer mon idée.

    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
    class Vehicle {...};
    class Car {...};
    class Motorbike {...};
    
    map["vehicule"] = Vehicle;
    map["voiture"] = Car;
    map["moto"] = Motorbike;
    
    fabrique(string vehicule, param1, param2)
    {
        return new map_vehicules["voiture"](, param1, param2);
    }
    
    main()
    {
        Vehicle toto = fabrique("voiture", param1, param2);
    }
    PS: dernièrement (pas plus d'un mois et demi), la question des fabriques est revenue dans le forum C&C++/Contribuez. D'autres solutions ont été évoquées.
    OK, je vais chercher ça en attendant.

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    OK. Deux choses quasi impératives:
    - un pseudo type commun (soit une classe véhicule), soit du boost.any en retour
    - que toutes tes constructions attendent les mêmes paramètres (nombre et type)

    Et là, la solution que j'avais donnée quand l'autre forum peut répondre à tes questions. Par contre ... la doc embarqué est à la rue complet.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Fais-tu référence à ce thread ?

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Oui.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    OK. Deux choses quasi impératives:
    - un pseudo type commun (soit une classe véhicule), soit du boost.any en retour
    Je conseillerais plutôt boost.Variant si le nombre de types possibles est fixé à l'avance.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Les types sont connus à l'avance, mais bien trop nombreux pour utiliser Boost.Variant.

    Mais néanmoins merci de m'avoir fait le mettre le nez dans cette lib.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    OK. Deux choses quasi impératives:
    - un pseudo type commun (soit une classe véhicule), soit du boost.any en retour
    - que toutes tes constructions attendent les mêmes paramètres (nombre et type)
    J'ai codé un truc avec Boost::function, mais ça ne fonctionne pas quand le constructeur prend des arguments.

    RDV dans la section Boost pour la suite. :-)

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Et avec des classes traits et des spécialisations partielles?:
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    class Mary {};
    class Poppins {};
     
    class Lord {};
    class Jim {};
     
    template<typename T> struct TraitAssociation{};
     
    template<> struct TraitAssociation<Mary>
    {
       typedef Poppins* ptypeRetour;
    };
    template<> struct TraitAssociation<Lord>
    {
       typedef Jim* ptypeRetour;
    };
     
    template<class T>
    typename TraitAssociation<T>::ptypeRetour CreerElement(const T&);
     
    template<>
    TraitAssociation<Mary>::ptypeRetour CreerElement<Mary>(const Mary&)
    {
       return new Poppins();
    }
     
    template<>
    TraitAssociation<Lord>::ptypeRetour  CreerElement<Lord>(const Lord&)
    {
       return new Jim();
    }
     
    int main()
    {
       Mary oMary;
       Lord oLord;
     
       delete CreerElement(oMary);
       delete CreerElement(oLord);
     
       return 0;
    }

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    C'est une solution, mais ça fait beaucoup de lignes de code.
    Je dois gérer des dizaines de types.

    Merci tout de même.

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bon, et avec des macros (je sais, c'est pas terrible les macros, mais de temps en temps) :
    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
    20
    21
    22
    23
    24
     
    class Mary {};
    class Poppins {};
     
    class Lord {};
    class Jim {};
     
    template<typename T> struct TraitAssociation{};
    template<class T>
    typename TraitAssociation<T>::ptypeRetour CreerElement(const T&);
     
    #define M_AjouterAssociation(Cle,Valeur)\
       template<> struct TraitAssociation<Cle>\
       {\
          typedef Valeur* ptypeRetour;\
       };\
       template<>\
       TraitAssociation<Cle>::ptypeRetour CreerElement<Cle>(const Cle&)\
       {\
          return new Valeur();\
       }
     
    M_AjouterAssociation(Mary,Poppins)
    M_AjouterAssociation(Lord,Jim)

Discussions similaires

  1. Problème "LoadModule ssl_module modules/mod_ssl.so"
    Par ldcarpathes dans le forum Apache
    Réponses: 9
    Dernier message: 24/01/2008, 11h07
  2. Formulaires : problème avec les slashes et les quotes
    Par GarGamel55 dans le forum Langage
    Réponses: 1
    Dernier message: 12/10/2005, 15h59

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