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 :

[C++] Demande pr�cision sur Pattern Factory


Sujet :

C++

  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut [C++] Demande pr�cision sur Pattern Factory
    Bonsoir,

    Je n'arrive pas � comprendre l'int�r�t du pattern Factory par rapport au polymorphisme.

    Voil� deux codes qui font la m�me chose :

    1�re version

    main.cpp
    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
    #include <iostream>
    #include "factory.h"
     
    using namespace std;
     
    int main()
    {
        Fabrique* factory = new Fabrique();
     
        if (factory)
        {
            Form* f1 = factory->create("cercle");
            Form* f2 = factory->create("carree");
            f1->Dessiner();
            f2->Dessiner();
     
            delete f1, f2, factory;
        }
     
        return 0;
    }
    factory.h
    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
     
    #ifndef FACTORY_H_INCLUDED
    #define FACTORY_H_INCLUDED
     
    #include "form.h"
     
    class Fabrique
    {
    public:
     
        Form* create(std::string quoi)
        {
            if (quoi == "cercle") return new Cercle();
            if (quoi == "carree") return new Carree();
            return NULL;
        }
    };
     
    #endif // FACTORY_H_INCLUDED
    form.h
    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
     
    #ifndef FORM_H_INCLUDED
    #define FORM_H_INCLUDED
     
    class Form
    {
        public:
            virtual void Dessiner() = 0;
    };
     
    class Cercle
        : public Form
    {
        public:
            Cercle(){};
            ~Cercle(){};
     
            inline virtual void Dessiner()
            {
                std::cout << "Je suis un cercle" << std::endl;
            }
    };
     
    class Carree
        : public Form
    {
        public:
            Carree(){};
            ~Carree(){};
     
            inline virtual void Dessiner()
            {
                std::cout << "Je suis un carree" << std::endl;
            }
    };
     
    #endif // FORM_H_INCLUDED
    2eme version :
    main.cpp
    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
     
    #include <iostream>
    #include "form.h"
     
    using namespace std;
     
    int main()
    {
        Form* f1 = new Cercle;
        f1->Dessiner();
     
        Form* f2 = new Carree;
        f2->Dessiner();
     
        delete f1, f2;
     
        return 0;
    }
    form.h
    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
     
    #ifndef FORM_H_INCLUDED
    #define FORM_H_INCLUDED
     
    class Form
    {
        public:
            virtual void Dessiner() = 0;
    };
     
    class Cercle
        : public Form
    {
        public:
            Cercle(){};
            ~Cercle(){};
     
            inline virtual void Dessiner()
            {
                std::cout << "Je suis un cercle" << std::endl;
            }
    };
     
    class Carree
        : public Form
    {
        public:
            Carree(){};
            ~Carree(){};
     
            inline virtual void Dessiner()
            {
                std::cout << "Je suis un carree" << std::endl;
            }
    };
     
    #endif // FORM_H_INCLUDED
    Pour moi, la 2eme version est plus facile d'utilisation pour un r�sultat identique.

    A mon avis, j'ai mal compris l'id�e du pattern Factory :
    http://come-david.developpez.com/tut...e=Fabrique#LIV

    Pourtant, je pense l'avoir bien impl�ment�...

    Pouvez vous m'�clairez d'avantage ?

    Merci � tous
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Imagine la situation suivante, � l'execution le programme demande � l'utilisateur ce qu'il veut cr�er sous la forme d'un identifiant (une chaine de caract�re, ou autre, peu importe) parmi un ensemble de possibilit�. La factory te permet de faire ca. Tu l'as mal impl�menter, normalement il y a une fonction qui permet d'enregistrer les divers �l�ment que tu veux cr�er. Relis le code de David Come, ou l'impl�mentation de ce pattern dans certaines biblioth�que : Poco, Loki.

  3. #3
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Le pattern factory a, justement, pour but de te permettre d'utiliser le polymorphisme sans avoir � t'inqui�ter du type r�el de l'objet cr��, et donc, en minimisant les d�pendances entre l'endroit o� l'objet polymorphe est utilis� et le type r�el de celui-ci.

    Dans le cas que tu pr�sentes, l'id�e est de permettre � l'utilisateur de connaitre l'existence de la fabrique d'une part et du type "Forme" d'autre part, sans s'inqui�ter du fait que Forme est d�riv� en plusieurs types particuliers.

    Apr�s tout: tant que tu te contente d'invoquer des comportements polymorphes tels que dessiner sur tes objets, tu n'as strictement pas besoin de savoir qu'il existe diff�rents type de Forme


    Cela te permet, non seulement, d'adopter un desing beaucoup plus simple, mais aussi, d'augmenter le respect du principe nomm� OCP (Open Close Principle)
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  4. #4
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par Flob90 Voir le message
    Imagine la situation suivante, � l'execution le programme demande � l'utilisateur ce qu'il veut cr�er sous la forme d'un identifiant (une chaine de caract�re, ou autre, peu importe) parmi un ensemble de possibilit�. La factory te permet de faire ca. Tu l'as mal impl�menter, normalement il y a une fonction qui permet d'enregistrer les divers �l�ment que tu veux cr�er. Relis le code de David Come, ou l'impl�mentation de ce pattern dans certaines biblioth�que : Poco, Loki.
    Dans un design Factory, il y a toujours une fonction Register ? Car j'ai (cru) voir des codes sans cette fonction et je n'en vois pas trop son utilit�

    Donc si je comprends bien, avec ce pattern, je peux demander � l'utilisateur de dessiner un cercle (en r�cup�rant sa saisie dans un cin par exemple) ou une autre forme parmi celle que j'ai programm�es ? Alors qu'avec du polymorphisme classique, c'est impossible... AI-je bien compris ?

    Citation Envoy� par koala01
    Dans le cas que tu pr�sentes, l'id�e est de permettre � l'utilisateur de connaitre l'existence de la fabrique d'une part et du type "Forme" d'autre part, sans s'inqui�ter du fait que Forme est d�riv� en plusieurs types particuliers.

    Apr�s tout: tant que tu te contente d'invoquer des comportements polymorphes tels que dessiner sur tes objets, tu n'as strictement pas besoin de savoir qu'il existe diff�rents type de Forme
    Je n'arrive pas � saisir ce que vous voulez dire et surtout l'int�r�t de ce pattern. Peut �tre que mon exemple est nul donc si vous aviez un autre exemple plus parlant sur le r�el int�r�t de ce pattern par rapport au polymorphisme classique, je suis preneur
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  5. #5
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Il n'y a pas de choix � faire entre ce pattern et le polymorphisme. Bien au contraire si tu utilises le pattern factory, tu utilises aussi le polymorphisme


    Le polymorphisme est un m�canisme qui permet d'avoir des comportements diff�rent selon le type r�el de l'objet et non le type statique (celui que "voit" le compilateur).

    La factory te permet de choisir que type d'objet cr�er de mani�re dynamique (ie � l'execution).


    L� o� tu utilises le polymorphisme c'est que ta fonction de cr�ation de ta factory va te retourner via pointeur (ou r�f�rence) sur un type de base des objets de types filles : le type r�el est celui du type fille que tu veux, le type statique est celui du type de base, d�s que tu vas utiliser ces objets le polymorphisme entre en jeu, les bonnes fonction sont appel�.

    Pour la fonction register, la mani�re classique de faire est avec celle-ci (il faut que tu enregistres pr�allablement les diff�rents objets (*) que tu veux pouvoir instancier ensuite). Pour des besoins pr�cis on peut peut-�tre s'en passer, mais c'est du cas par cas


    Regardes ceci : http://pocoproject.org/slides/030-MemoryManagement.pdf (pages 31 � 38), c'est la factory propos� par Poco (*). Tu peux aussi regarder le code (il y a des �l�ment multi-thread dedans, oublie les dans un premier temps). Je trouve l'interface assez simple et clair (Loki est plus complexe)



    (*) Pour �tre plus pr�cis ce peut �tre des objets d'un type diff�rent qui permet de cr�er des objets des types voulus.

  6. #6
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Le polymorphisme, c'est avant tout manipuler divers objets sans conna�tre leur type exact. Or il y a un moment o� la connaissance du type exact est n�cessaire : La cr�ation de l'objet.

    Le but du pattern factory est d'encapsuler la connaissance du type exact � la cr�ation, de mani�re � avoir un choix flexible de ce type.

    A titre d'exo, je t'invite � �crire du code pour sauver dans un fichier, puis surtout recharger de ce fichier, un vector<Form*>. L'int�r�t de la factory devrait t'appara�tre.

    La notion de register est tr�s importante, mais j'avoue que je m'en passe assez souvent quand je dois code rapidement un prototype. Un des concepts de l'orient� objet est l'open-closed principle : On peut modifier le comportement d'un code en ajoutant du code, mais sans modifier le code existant. C'est � �a que sert register : Tu peux ajouter une nouvelle classe � celles g�r�es par la factory, sans changer une ligne de code dans le code existant, simplement en enregistrant ta nouvelle classe.
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  7. #7
    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 Aspic Voir le message
    Form* f1 = factory->create("cercle");
    Form* f2 = factory->create("carree");
    Imagine maintenant que tu as un programme en ligne de commande, et que c'est en cours d'ex�cution que l'utilisateur demande au programme de cr�er un cercle ou un carr�.

  8. #8
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par JolyLoic Voir le message
    Le polymorphisme, c'est avant tout manipuler divers objets sans conna�tre leur type exact. Or il y a un moment o� la connaissance du type exact est n�cessaire : La cr�ation de l'objet.

    Le but du pattern factory est d'encapsuler la connaissance du type exact � la cr�ation, de mani�re � avoir un choix flexible de ce type.

    A titre d'exo, je t'invite � �crire du code pour sauver dans un fichier, puis surtout recharger de ce fichier, un vector<Form*>. L'int�r�t de la factory devrait t'appara�tre.

    La notion de register est tr�s importante, mais j'avoue que je m'en passe assez souvent quand je dois code rapidement un prototype. Un des concepts de l'orient� objet est l'open-closed principle : On peut modifier le comportement d'un code en ajoutant du code, mais sans modifier le code existant. C'est � �a que sert register : Tu peux ajouter une nouvelle classe � celles g�r�es par la factory, sans changer une ligne de code dans le code existant, simplement en enregistrant ta nouvelle classe.
    Je crois que je commence � comprendre l'utilit� de ce pattern. Avec ton exemple, sans la factory, il est impossible de charger des classes � partir d'un fichier texte

    Par contre, je suis entrain d'impl�menter la version avec un register mais j'ai un probl�me car je ne veux pas cr�er les objets en les clonant mais en utilisant "new" :
    Citation Envoy� par tutoriel de come-david
    Avant toute chose, il faut pr�ciser comment seront cr��s les objets. En effet, sur ce point, plusieurs strat�gies sont envisageables telle la cr�ation via new ou celle par clonage. Pour ma part, j'ai choisi celle bas�e sur le clonage. Mais vous trouverez facilement d'autres impl�mentations sur le web.
    Je vous donne mon code :
    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
    class Fabrique
    {
    public:
     
        std::map<std::string, Form*> m_map;
     
        //Fonction qui associe clé <=> prototype
        void Register(const std::string& key, Form* obj)
        {
            //si la clé n'est pas déjà présente
            if(m_map.find(key)==m_map.end())
            {
                //on ajoute l'objet dans la map
                m_map[key] = obj;
            }
        }
     
     
        Form* create(const std::string& key)
        {
            Form* tmp = NULL;
            std::map<std::string, Form*>::const_iterator it = m_map.find(key);
     
            //si l'itérateur ne vaut pas map.end(), cela signifie que que la clé à été trouvée
            if(it != m_map.end())
            {
                //tmp = (*it).second->Clone();
                // ici comment dire si je veux un carree alors faire new Caree(); ...
            }
     
            return tmp;
        }
    };
    Dans tous les codes sur le net, ils utilisent des if pour faire un truc du genre :
    // Si key == "carree" alors return new Carree();
    // si key == "cercle" alors return new Cercle();
    Sauf que si j'ai bien compris et que je veux respecter l'open-closed en POO, je ne dois pas modifier le code de la classe si je d�cide d'enregistrer une nouvelle classe.
    Or avec la technique des "if" je dois modifier le code � chaque ajout... D'o� l'utilisation d'une map je suppose mais encore une fois, je ne vois pas comment faire

    EDIT :
    J'ai vu que la fonction Register �tait statique. Est-ce obligatoire ? qu'est ce que ca change concr�tement ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  9. #9
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    As-tu regarder l'interface propos� par Poco ? C'est vraiment instructif.

    Voila en gros � quoi ca ressemble (code partiel) :
    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
     
    #include <map>
    #include <string>
     
    template<class Base>
    struct Instanciator
    {
      virtual Base* create() =0;
      virtual ~Instanciator() {}
    };
     
    template<class Base, class Fille>
    struct NewInstanciator : Instanciator<Base>
    {
      Base* create()
      { return new Fille(); }
    };
     
    template<class Base>
    class Factory
    {
      std::map<std::string,Instanciator<Base>*> map_;
      public:
        void register_class(const std::string& id,Instanciator<Base>* inst)
        { map_[id] = inst; /*gérer les cas où l'id est déjà enregistrer*/ }
        template<class Fille>
        void register_class(const std::string& id)
        { register_class(id,new NewInstanciator<Base,Fille>()); }
        Base* create(const std::string& id)
        { return map_.at(id).create(); }
        ~Factory()
        { /*détruire les instanciators*/ }
    };
     
    template<class Base,class Fille>
    class CloneInstanciator : public Instanciator<Base>
    {
      Fille* to_clone;
      public:
        CloneInstanciator(Fille* f) : to_clone(f) {}
        Base* create()
        { return to_clone.clone(); }
    };
    Cette facon de faire permet de laisse le choix de la politique de cr�ation (clone ou new) hors de la classe. On enregistre des instanciator (via des pointeurs) qui h�ritent d'un type commun (Instanciator<Base>) et poss�de une m�thode de cr�ation (Base* create()).

    On peut aussi faire une seconde fonction d'enregistrement template qui permet d'enregistrer un instanciator en connaisant le type r�el.

  10. #10
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Perso, j�utilise g�n�ralement un map<string, function<Base*()> >
    Avec function == boost::function, ou std::function pour un compilateur r�cent, et �ventuellement des param�tres suppl�mentaires si toutes les classes de ma hi�rarchie ont besoin de tels param�tres.

    Mais c'est pas forc�ment hyper facile � comprendre. Une map contenant des pointeurs de fonction est moralement �quivalent (mais moins souple):

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    typedef Base* (*Creator)();
    map<string, Creator> maMap;
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  11. #11
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Je vous avoue que je suis perdu
    Les templates c'est pas trop mon truc m�me si je sais les utiliser. Mais cette histoire de classe Instanciator m'a perdu compl�tement.

    Concr�tement faire la cr�ation des objets par un new ou par une m�thode de clonage ca change quoi ?

    EDIT :
    Dans son tutoriel, il dit qu'il fait la cr�ation par clonage masi pourquoi ca proc�dure de clonage ne fait qu'un new ?
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    Figure* Cercle::Clone() const 
    { 
            return new Cercle(*this);
    }
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  12. #12
    Membre Expert

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 49
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - Op�rateur de t�l�communications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par d�faut
    Pour simplifier ce qui a �t� dit, on utilise le pattern factory pour cr�er des objets dont la classe n'est pas connue au moment de la compilation - le choix s'effectuant donc au runtime. Par rapport � une approche bas�e sur une s�rie de if, le pattern factory permet un meilleur respect d'un principe d'architecture objet nomm� "principe ouvert/ferm�".

    En gros, il est plus facile et plus maintenable de faire :

    objbuilder* obj_builder = new my_new_object_builder();
    factory,register(obj_builder);
    ...
    object* o = factory.create(some_particular_id);
    Que de modifier un gros if avec des dizaines de cas.
    [FAQ des forums][FAQ D�veloppement 2D, 3D et Jeux][Si vous ne savez pas ou vous en �tes...]
    Essayez d'�crire clairement (c'est � dire avec des mots fran�ais complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Caf�. C'est d�pass� tout �a.
    Et si vous �tes sages, vous aurez peut �tre vous aussi la chance de passer � la t�l�. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  13. #13
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par Emmanuel Deloget Voir le message
    Pour simplifier ce qui a �t� dit, on utilise le pattern factory pour cr�er des objets dont la classe n'est pas connue au moment de la compilation - le choix s'effectuant donc au runtime. Par rapport � une approche bas�e sur une s�rie de if, le pattern factory permet un meilleur respect d'un principe d'architecture objet nomm� "principe ouvert/ferm�".

    En gros, il est plus facile et plus maintenable de faire :



    Que de modifier un gros if avec des dizaines de cas.
    Ca il n'y a pas de probl�me, j'ai compris l'int�r�t de la fonction Register

    Mais j'aimerais bien comprendre les codes de JolyLoic et
    Flob90 car ils ont l'air int�ressant est tr�s flexibles.
    Et je n'aime pas recopier du code sans comprendre ce qu'il fait c'est pour ca que je m'acharne � essayer de comprendre des principes pas �vidents

    Est ce que vous pourriez (Flob90, JolyLoic ou quelqu'un d'autre ) me donner la version sans template et appliqu� � mes classes (� savoir Form, Carree, Cercle et Factory) histoire que je comprenne le principe ? Apr�s je m'occuperais de templatis� tout ca quand j'aurais bien compris le fonctionnement

    Merci !
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  14. #14
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    EDIT :
    Dans son tutoriel, il dit qu'il fait la cr�ation par clonage masi pourquoi ca proc�dure de clonage ne fait qu'un new ?
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    Figure* Cercle::Clone() const 
    { 
            return new Cercle(*this);
    }
    http://cpp.developpez.com/faq/cpp/?p...es#CLASS_clone devrait te donner une meilleure compr�hension.
    Citation Envoy� par Aspic Voir le message
    Est ce que vous pourriez (Flob90, JolyLoic ou quelqu'un d'autre ) me donner la version sans template et appliqu� � mes classes (� savoir Form, Carree, Cercle et Factory) histoire que je comprenne le principe ? Apr�s je m'occuperais de templatis� tout ca quand j'aurais bien compris le fonctionnement
    L'exemple que j'ai donn� avec Creator est sans template (mais avec pointeur de fonction).
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  15. #15
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Ok j'ai compris pour la pattern Clone (et hop un nouveau pattern d�couvert ^^)

    Ok je crois que j'ai r�ussi � impl�menter la version avec template. Pouvez vous v�rfier que j'ai fais de b�tises ?
    factory.h
    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
    #ifndef FACTORY_H_INCLUDED
    #define FACTORY_H_INCLUDED
     
    #include <map>
    #include <string>
     
    template<class Base>
    struct Instanciator
    {
        virtual Base* create() =0;
        virtual ~Instanciator() {}
    };
     
    template<class Base, class Fille>
    struct NewInstanciator
        : public Instanciator<Base>
    {
        Base* create()
        {
            return new Fille();
        }
    };
     
    template<class Base, class Fille>
    class CloneInstanciator
        : public Instanciator<Base>
    {
        Fille* to_clone;
    public:
        CloneInstanciator(Fille* f) : to_clone(f) {}
        Base* create()
        {
            return to_clone->Clone();
        }
    };
     
    template <class Base>
    class Factory2
    {
        std::map<std::string,Instanciator<Base>*> map_;
    public:
        void register_class(const std::string& id, Instanciator<Base>* inst)
        {
            /*gérer les cas où l'id est déjà enregistrer*/
            //si la clé n'est pas déjà présente
            if(map_.find(id)==map_.end())
            {
                //on ajoute l'objet dans la map
                map_[id] = inst;
            }
        }
     
        template<class Fille>
        void register_class(const std::string& id)
        {
            register_class(id,new NewInstanciator<Base, Fille>());
        }
     
        Base* create(const std::string& id)
        {
            return map_.at(id)->create();
        }
        ~Factory2()
        {
            /*détruire les instanciators*/
            typename std::map<std::string,Instanciator<Base>*>::iterator it;
     
            for(it=map_.begin() ; it!=map_.end() ; ++it)
            {
                delete it->second; // accede à la valeur donc à Instanciator*
            }
        }
    };
     
    #endif // FACTORY_H_INCLUDED
    Form.h et Form.cpp
    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
    #ifndef FORM_H_INCLUDED
    #define FORM_H_INCLUDED
     
    //la classe prototype abordé en II
    template <class T>
    class Prototype
    {
        public:
        virtual ~Prototype(){}
        virtual T* Clone() const = 0;
    };
     
    class Form
        : public Prototype<Form>
    {
        public:
            virtual void Dessiner() = 0;
    };
     
    class Cercle
        : public Form
    {
        public:
            Cercle();
            ~Cercle();
     
            void Dessiner();
            Form* Clone() const;
    };
     
    class Carree
        : public Form
    {
        public:
            Carree();
            ~Carree();
     
            void Dessiner();
            Form* Clone() const;
    };
     
    class Triangle
        : public Form
    {
        public:
            Triangle();
            ~Triangle();
     
            void Dessiner();
            Form* Clone() const;
    };
     
    #endif // FORM_H_INCLUDED
    #include "form.h"
    #include <iostream>
     
    Cercle::Cercle(){}
    Cercle::~Cercle(){}
     
    void Cercle::Dessiner()
    {
        std::cout << "Je suis un cercle" << std::endl;
    }
     
    Form* Cercle::Clone() const
    {
        return new Cercle(*this);
    }
     
    Carree::Carree(){}
    Carree::~Carree(){}
     
    void Carree::Dessiner()
    {
        std::cout << "Je suis un carree" << std::endl;
    }
     
    Form* Carree::Clone() const
    {
        return new Carree(*this);
    }
     
     
    Triangle::Triangle(){}
    Triangle::~Triangle(){}
     
    void Triangle::Dessiner()
    {
        std::cout << "Je suis un Triangle" << std::endl;
    }
     
    Form* Triangle::Clone() const
    {
        return new Triangle(*this);
    }
    Et enfin le main.cpp
    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
    #include <iostream>
    #include "factory.h"
    #include "form.h"
     
    using namespace std;
     
    int main()
    {
        Factory2<Form>* fac = new Factory2<Form>();
     
        fac->register_class<Carree>("carre");
        //equivalent à fac->register_class("carre", new NewInstanciator<Form, Carree>());
     
        fac->register_class("cercle", new CloneInstanciator<Form, Cercle>(new Cercle));
     
        Form* f1 = fac->create("carre");
        f1->Dessiner();
        Form* f2 = fac->create("cercle");
        f2->Dessiner();
     
        delete f1;
        delete f2;
        delete fac;
     
        return 0;
    }
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  16. #16
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Oui c'est ca, dans ton exemple, les carr� sont cr�er avec un politique de type "new" et les cercle une politique par clonage.

    Un oublie dans le code que j'avais post� (et donc dans le tiens) dans CloneInstanciator il faut plut�t utiliser un std::unique_ptr<Fille> pour to_clone, sinon il y a une fuite m�moire. (ca implique que le CloneInstanciator est responsable de la dur�e de vie de l'objet � cloner).

    Ce que propose par JolyLoic est similaire, on remplace juste les instanciators par des std::function<Base*()> (ou autre type de functor) et � la place d'appeler la fonction create tu appeles le foncteur. Le principe est le m�me : tu as un objet qui te cr�� ce que tu lui demande. C'est � cette objet de choisir comment le cr�er : new, clone, autre.

    NB: Les templates servent juste � pas avoir � �crire les instanciator pour chaque type : le code de NewInstanciator ou CloneInstanciator est � chaque fois le m�me. Tu peux les enl�ver mais tu vas avoir un duplication de code assez grosse, AMA

  17. #17
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Parfait, merci ! justement j'allais test� les fuites de m�moire merci pour l'info ^^

    Encore une derni�re pr�cision, j'ai vu que la m�thode Register �tait statique dans le tuto de come-david, pourquoi cela ?

    Sinon � titre d'application de ce pattern, est ce que dans la situation pr�sente, l'utilisation de la Fabrique est justifi�e ou pas :
    Soit une classe Object qui g�re des objets de tout type comme des coeurs, potions, rochers, blocs... sachant que chaque type d'objet poss�de des caract�ristiques pr�cises. Exemple : les rochers peuvent se briser mais pas se pousser alors qu'un bloc pour se pousser (et m�me on peut le porter...). Les coeurs et les potions sont "collectables" comme dans 90% des jeux.
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  18. #18
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    Parfait, merci ! justement j'allais test� les fuites de m�moire merci pour l'info ^^

    Encore une derni�re pr�cision, j'ai vu que la m�thode Register �tait statique dans le tuto de come-david, pourquoi cela ?

    Sinon � titre d'application de ce pattern, est ce que dans la situation pr�sente, l'utilisation de la Fabrique est justifi�e ou pas :
    Soit une classe Object qui g�re des objets de tout type comme des coeurs, potions, rochers, blocs... sachant que chaque type d'objet poss�de des caract�ristiques pr�cises. Exemple : les rochers peuvent se briser mais pas se pousser alors qu'un bloc pour se pousser (et m�me on peut le porter...). Les coeurs et les potions sont "collectables" comme dans 90% des jeux.
    J'aurais tendance � dire qu'il faut faire attention de ne pas tomber dans le pi�ge du "god object"...

    Il serait peut etre plus int�ressant de regrouper les types selon leur utilit� (objets "utilisable" d'un cot�, �l�ments d�cors de l'autre, armes d'un troisi�me, armures d'un quatri�me, etc)

    et d'avoir, au final, autant de fabrique et de gestionnaires que... d'utilit�s envisag�es.

    Cela simplifiera sans doute �norm�ment la gestion au quotidien de tous tes objets, m�me si on peut imaginer qu'ils pr�sentent malgr� tout une interface commune ( void use() ) ne serait-ce que parce que tu ne devras plus tester syst�matiquement si tu as affaire � une potion, � un bijou ou � une arme

    Par contre, un petit coup de template t'aidera surement � �viter la duplication de code
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  19. #19
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par koala01 Voir le message
    J'aurais tendance � dire qu'il faut faire attention de ne pas tomber dans le pi�ge du "god object"...

    Il serait peut etre plus int�ressant de regrouper les types selon leur utilit� (objets "utilisable" d'un cot�, �l�ments d�cors de l'autre, armes d'un troisi�me, armures d'un quatri�me, etc)

    et d'avoir, au final, autant de fabrique et de gestionnaires que... d'utilit�s envisag�es.

    Cela simplifiera sans doute �norm�ment la gestion au quotidien de tous tes objets, m�me si on peut imaginer qu'ils pr�sentent malgr� tout une interface commune ( void use() ) ne serait-ce que parce que tu ne devras plus tester syst�matiquement si tu as affaire � une potion, � un bijou ou � une arme

    Par contre, un petit coup de template t'aidera surement � �viter la duplication de code
    Donc si je comprends bien, je vais avoir une classe M�re ObjetUtilisable avec des classes Filles Coeur, Potion...
    Une autre classe M�re ObjetDecors avec comme classes Filles Rocher, Herbe, Bloc, Mur...

    Mais o� sont les Fabriques dans ce cas ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  20. #20
    screetch
    Invit�(e)
    Par d�faut
    c'est une (tr�s) mauvaise id�e d'avoir des classes our chaque type d'objet.

    Un moyen plus flexibe et bien meilleur au lieu de l'h�ritage, c'est la composition; un Objet est compos� d'aspects, un aspect est par exemple son aspect a l'ecran (son sprite)
    un autre aspect c'est son aspect "poussable"
    un autre aspect c'est "cassable", ou bien "ramassable"

    ca permet de cr�er des entit�s qui sont a la fois Utilisable et Ramassable, sans avoir de l'heritage multiple ou pire, de l'heritage foireux.

    L'heritage de toutes facons c'est le mal.

+ R�pondre � la discussion
Cette discussion est r�solue.
Page 1 sur 2 12 Derni�reDerni�re

Discussions similaires

  1. R�ponses: 16
    Dernier message: 26/08/2011, 22h02
  2. [MySQL] Demande pr�cisions sur LOCK TABLE
    Par renaud26 dans le forum PHP & Base de donn�es
    R�ponses: 8
    Dernier message: 15/04/2011, 13h49
  3. Demande de pr�cision sur "Extends" ..
    Par Invit� dans le forum Langage
    R�ponses: 6
    Dernier message: 12/02/2006, 14h25
  4. Demande de pr�cisions sur Backup/Restore et transactions
    Par lio33 dans le forum Connexion aux bases de donn�es
    R�ponses: 1
    Dernier message: 16/11/2005, 12h08
  5. [Observateur] Pr�cisions sur le design pattern Observer [UML]
    Par joquetino dans le forum Design Patterns
    R�ponses: 2
    Dernier message: 07/10/2004, 22h35

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