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

Contribuez C++ Discussion :

[Source C++] Une fabrique assez modulaire


Sujet :

Contribuez C++

  1. #1
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut [Source C++] Une fabrique assez modulaire
    Bonjour à tous.
    J'ai réalisé une implémentation du design pattern fabrique:
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
     
     
    /*
    Implementation d'une fabrique generique basee sur des classes de politiques,
    par Côme David.
    */
     
    /*
    NOTE: Dans le passage de key, on pourrait utiliser la choix automatique de type
    presente dans l'article d'Alp Mestan sur les traits et classes politiques
    */
     
    #include <iostream>
    #include <map>
     
    //La structure d'heritage, triviale a souhait
    struct Shape{virtual void draw()=0;virtual Shape* Clone()=0;};
    struct Square: Shape 
    {
        void draw(){std::cout<<"Square"<<std::endl;}
        Square* Clone(){return new Square(*this);}
    };
    struct Circle: Shape {
        void draw(){std::cout<<"Circle"<<std::endl;}
        Circle* Clone(){return new Circle(*this);}
    };
    struct Triangle : Shape{
        void draw(){std::cout<<"Triangle"<<std::endl;}
        Triangle* Clone(){return new Triangle(*this);}
    };
    //========================================================
    /* Une premiere classe de politique de creation. Elle se base
       sur le clonage des objets contenus dans la map.
     
       l'utilisation des concepts de C++0x permettra de verifier s'il possede
       bien une fonction membre Clone.
     */
    template <typename Key,typename Object> struct CloneCreator
    {
        //on ajoute une cle avec un objet si la cle n'est déjÃ* pas présente
        void Register(Key key,Object* obj)
        {
    	if(m_map.find(key)==m_map.end()) { m_map[key]=obj;}
        }
     
        //Un creer un nouvel Objet via l'appel Ã* la fonction polymorphique Clone 
        //qui utilise aussi des retours covariants
        Object* Create (const Key& key) const 
        {
    	Object* tmp=0;
     
    	typename std::map<Key,Object*>::const_iterator it=m_map.find(key);
    	if(it!=m_map.end()) { tmp=((*it).second)->Clone();}
    	/*else {throw } //On pourrai lancer une exception si on le souhaite*/
    	return tmp;
        }
     
        ~CloneCreator()
        {
    	typename std::map<Key,Object*>::iterator ite=m_map.end();
    	typename std::map<Key,Object*>::iterator it=m_map.begin();
    	for(;it!=ite;it++)
    	{
    	    delete (*it).second;
    	}
        }
    private:
        std::map<Key,Object*> m_map;
    };
    //========================================================
    /* Une 2eme politique qui se base sur l'appel de fonction 
       pour generer de nouveau objets. La seule contrainte de la fonction
       est sa signature. Doit renvoyer un pointeur sur Objet* et ne prendre 
       aucun paramètre. On pourrai aussi utiliser des boost::function si on souhaite 
       ameliorer le tout
     */
    template <typename Key,typename Object> struct FonctionCreator
    {
     
        void Register(Key key,Object* (*obj)())
        {
    	if(m_map.find(key)==m_map.end()) { m_map[key]=obj;}
        }
     
        Object* Create (const Key& key) const 
        {
    	Object* tmp=0;
     
    	typename std::map<Key,Object* (*)()>::const_iterator it=m_map.find(key);
    	if(it!=m_map.end()) { tmp=((*it).second)();}
     
    	return tmp;
        }
     
    private:
        std::map<Key,Object* (*)()> m_map;
    };
    //========================================================
    //la fabrique a proprement parle. Ne fait que des apples a la classe de poltique.
    template 
    <
    typename Key,typename Object,
        template <class U,class V> class PolicieCreation = FonctionCreator
    > 
    struct Fabrique
    {
        /* 
           C'est ici que reside toute la puissance de la fabrique: grace a cette 
           fonction template, on peut utiliser Register sur n'importe quoi, tant que
           c'est homogene ala partie "non-cle" dans la map de la classe politique
         */
        template <class Way> void Register(Key key,Way obj){creator.Register(key,obj);}
       Object* Create(Key key){creator.Create(key);}
    private:
        PolicieCreation<Key,Object> creator;
    };
     
     
        /*Des fonctions de creation pour FonctionCreator
        A noter: elle font appel au constructeur par defaut, mais on pourrait
        tout aussi bien faire appel au constructeur de recopie, ce qui fait qu'au
        final, l'effet ne serrai pas different de CloneCreator
        */
    namespace 
    {
        Shape* CreateCircle(){return new Circle();}
        Shape* CreateSquare(){return new Square();}
        Shape* CreateTriangle(){return new Triangle();}
    }
    #define CLONE
     
    int main(int argc, char const *argv[])
    {
     
    #ifdef CLONE
        Fabrique<std::string,Shape,CloneCreator> c;
        c.Register("Square",new Square);
        c.Register("Circle",new Circle);
        c.Register("Triangle",new Triangle);
    #else
        Fabrique<std::string,Shape,FonctionCreator> c;
        c.Register("Square",&CreateSquare);
        c.Register("Circle",&CreateCircle);    
        c.Register("Triangle",&CreateTriangle);
    #endif
     
        Shape *p= c.Create("Circle");
        p->draw();
        delete p;
     
        return 0;
    }
    Vos avis ?
    Merci.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    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 292
    Par défaut
    Il me manquerait la possibilité de créer avec des arguments. Et éventuellement les modèles chain et stream factories.

    Il y a quelques temps, j'avais pondu un truc à mi-chemin entre loki et les pluggable factories(*) :
    - lib
    - tests
    (la doc est à l'ouest)

    (*) voir le .hpp pour une adresse où trouver une archive du vieil article du feu C++ Report.
    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
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Il me manquerait la possibilité de créer avec des arguments.
    J'ai pas mal cherché pour arriver à quelque chose potable, mais rien n'est apparu en utilsant que la STL.

    Et éventuellement les modèles chain et stream factories.
    Les chain factories, j'ai compris, par contre celui des stream factories, je ne voie pas ce que ca veux dire.

    Il y a quelques temps, j'avais pondu un truc à mi-chemin entre loki et les pluggable factories(*) :
    - lib
    - tests
    (la doc est à l'ouest)

    (*) voir le .hpp pour une adresse où trouver une archive du vieil article du feu C++ Report.
    TU m'avais déjà montré ce code, et disons que là, je le pige à peu près
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    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 292
    Par défaut
    La StreamFactory est une ChainFactory qui extrait ses infos depuis un istream.

    Pour la compréhension du code, je m'étais beaucoup inspiré du travail dans Modern C++ Design avant d'adapter des idée de Timothy R Culp [NB: passez par archive.org pour obtenir une version de l'article -> http://web.archive.org/web/200602191...le.asp?ID=1520]
    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
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Pour le choix du type à passer concernant Key que je donne, tu parles de :
    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
    template <typename T>
    struct CallTraits
    {
        template <typename U, bool Big> struct CallTraitsImpl;
     
        template <typename U>
        struct CallTraitsImpl<U, true>
        {
            typedef const U& Type;
        };
     
        template <typename U>
        struct CallTraitsImpl<U, false>
        {
            typedef U Type;
        };
     
        typedef typename CallTraitsImpl<T, (sizeof(T) > 8)>::Type ParamType;
    };
    ?

    Sinon, bon boulot et pour des améliorations faut voir du côté du code de Luc que j'ai déjà lu et relu de nombreuses fois

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Ouaip, c'est bien de ce code dont je parle.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

Discussions similaires

  1. Réponses: 16
    Dernier message: 12/11/2004, 00h05
  2. [Juridique] Comment réutiliser le code source d'une classe ?
    Par mathieu dans le forum Général Java
    Réponses: 8
    Dernier message: 17/05/2004, 13h40
  3. Source attachée à une classe
    Par Lyr7in3 dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 12/05/2004, 14h44
  4. [VB6] Source D'une erreur
    Par krest dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 16/07/2003, 17h33
  5. Recuperation du source d'une page - envoi de param
    Par ulysse66x dans le forum Web & réseau
    Réponses: 3
    Dernier message: 15/06/2003, 17h31

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