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++/CLI Discussion :

Design pattern : factory


Sujet :

C++/CLI

  1. #1
    Membre averti
    Homme Profil pro
    Analyse syst�me
    Inscrit en
    Novembre 2014
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Analyse syst�me

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par d�faut Design pattern : factory
    Bonjour,
    J'essaye d'impl�menter pour la premi�re fois le design pattern factory en C++.
    J'ai donc une classe Object d�fini comme suit :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    class Object {
     
    public:
    	virtual Object* clone() = 0;
    };
    Et une classe Tile qui en h�rite :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    class Tile : public Object {
    public:
    	Tile();
            getId();
    	Object* clone();
    };
    (Pour l'instant je n'ai que celle l� mais � l'avenir d'autres viendrons s'ajouter)

    Enfin voici ma classe objectfactory qui est d'ailleurs un singleton :
    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
    class ObjectFactory : Singleton<ObjectFactory> {
    friend class Singleton<ObjectFactory>;
     
    private:
    	ObjectFactory();
    	~ObjectFactory();
     
    public:
    	void add(std::string const& key, Object* obj) {
    		_mapFactory[key] = obj;
    	}
    	Object* construct(std::string const& key) {
    		Object* tmp = 0;
    		tmp = _mapFactory.at(key)->clone();
    		return tmp;	
    	}
    private:
    	std::map<std::string, Object*> _mapFactory;
    };
    Le probl�me viens que je peut �crire ce code :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    ObjectFactory* obj = Singleton<ObjectFactory>::instance();
    obj->add("Tile", new Tile);
    Object* t = obj->construct("Tile");
    Mais apr�s je ne peux rien faire faire avec mon objet t. Je ne peux pas acc�der aux m�thodes de Tile. Je ne peux par exemple par �crire :
    Comment r�soudre ce probl�me ? Merci de votre aide !

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par d�faut
    Bonjour,

    L'int�r�t du patron de conception Factory method, c'est de pouvoir ne pas conna�tre � la compilation le type r�el de l'objet construit.

    Ta m�thode Object* construct(std::string const& key) permet de construire un objet dont le type r�el est inconnu � la compilation, mis � part le fait que ce type doit d�river de Object. Mais, en contrepartie, effectivement, tu ne peux pas appeler des m�thodes absentes de la classe Object.

    Si tu as besoin en plus de construire un objet pour lequel le compilateur doit savoir que le type d�rive de Tile, il faut ajouter une fonction Tile* constructTile(std::string const& key) const ou, encore mieux, std::unique_ptr<Tile> constructTile(std::string const& key) const.

    Voici le code correspondant (j'ai tout recod�) :
    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
    #include <iostream>
    #include <map>
    #include <memory>
    #include <string>
     
    template<class T>
    class SingletonCRTP
    {
        SingletonCRTP(SingletonCRTP const& other)            = delete;
        SingletonCRTP& operator=(SingletonCRTP const& other) = delete;
    public:
        static T& instance() {return _instance;}
    protected:
        SingletonCRTP() {}
    private:
        static T _instance;
    };
     
    template<class T>
    T SingletonCRTP<T>::_instance;
     
    class Object
    { 
    public:
        virtual ~Object() {}
        inline std::unique_ptr<Object> clone() const
        {
            return std::unique_ptr<Object>(virtClone());
        }
    private:
        virtual Object* virtClone() const = 0;
    };
     
    class Tile : public Object
    {
    public:
        explicit Tile(int id) : _id(id) {}
        ~Tile() override {}
        inline std::unique_ptr<Tile> clone() const
        {
            return std::unique_ptr<Tile>(virtClone());
        }
        inline int getId() const {return _id;}
    private:
        Tile* virtClone() const override
        {
            return new Tile(*this);
        }
        int _id;
    };
     
    class ObjectFactory : public SingletonCRTP<ObjectFactory>
    {
        friend class SingletonCRTP<ObjectFactory>;
    private:
        ObjectFactory()  {}
        ~ObjectFactory() {}
    public:
        void addObject(std::string const& key, Object const& obj)
        {
            _mapFactoryObject[key] = &obj;
        }
        void addTile(std::string const& key, Tile const& tile)
        {
            _mapFactoryObject[key] = &tile;
            _mapFactoryTile  [key] = &tile;
        }
        std::unique_ptr<Object> constructObject(std::string const& key) const
        {
            Object const* tmp = _mapFactoryObject.at(key);
            return tmp->clone();    
        }
        std::unique_ptr<Tile> constructTile(std::string const& key) const
        {
            Tile const* tmp = _mapFactoryTile.at(key);
            return tmp->clone();    
        }
    private:
        std::map<std::string, Object const*> _mapFactoryObject;
        std::map<std::string, Tile   const*> _mapFactoryTile;
    };
     
    int main()
    {
        ObjectFactory& objectFactory = ObjectFactory::instance();
        Tile tile1(1);
        Tile tile2(2);
        objectFactory.addTile("Tile 1", tile1);
        objectFactory.addTile("Tile 2", tile2);
        std::unique_ptr<Tile> toto = objectFactory.constructTile("Tile 1");
        std::cout << "Id de toto : " << toto->getId() << "\n";
        return 0;
    }
    Remarques sur le code :
    • Ne pas oublier const pour les m�thodes qui ne modifient pas l'objet.
    • Quand c'est possible, pr�f�rer une r�f�rence � un pointeur si ledit pointeur doit �tre non nul. => FAQ C++
    • Pr�f�rer std::unique_ptr � un pointeur nu si ledit pointeur est responsable de lib�rer la ressource. => FAQ C++
    • Dans une classe A, quand une fonction virtuelle foo retourne un pointeur ou une r�f�rence vers une classe X alors, dans une classe B qui d�rive de A, on peut modifier le type de retour de B::foo en un pointeur ou une r�f�rence vers une classe Y qui d�rive de X. C'est le principe des types de retour covariants.
      Cela permet � l'utilisateur d'�viter de faire sauvagement du downcasting de X vers Y.
      Dans mon code, j'ai utilis� ce principe avec foo = virtClone() const, A = X = Object et B = Y = Tile.

  3. #3
    Membre averti
    Homme Profil pro
    Analyse syst�me
    Inscrit en
    Novembre 2014
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Analyse syst�me

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par d�faut
    Merci de ta r�ponse.
    Maintenant si j'ai plusieurs cas comme Tile ? Imaginons que j'ai plusieurs objets qui doivent �tre cr�er de la m�me fa�on...
    Au d�but j��tais partit sur une id�e de if..elseif ou je cr�er l'objet en fonction mais �a demander de rajouter du code � chaque fois...

  4. #4
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par d�faut
    Citation Envoy� par loustak Voir le message
    Maintenant si j'ai plusieurs cas comme Tile ?
    Je viens de modifier le code :
    • J'ai cr�� un mod�le de classe ObjectFactory<T>.
    • Quand on ajoute un Tile dans ObjectFactory<Tile>, �a l'ajoute aussi dans ObjectFactory<Object>.
    • J'ai ajout� une classe TileDeriv qui d�rive de Tile. Quand on ajoute un TileDeriv dans ObjectFactory<TileDeriv>, �a l'ajoute aussi dans ObjectFactory<Tile> et dans ObjectFactory<Object>.


    Voici le code modifi� :
    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
    #include <iostream>
    #include <map>
    #include <memory>
    #include <string>
     
    template<class T>
    class SingletonCRTP
    {
        SingletonCRTP(SingletonCRTP const& other)            = delete;
        SingletonCRTP& operator=(SingletonCRTP const& other) = delete;
    public:
        static T& instance() {return _instance;}
    protected:
        SingletonCRTP() {}
    private:
        static T _instance;
    };
     
    template<class T>
    T SingletonCRTP<T>::_instance;
     
    class Object
    { 
    public:
        virtual ~Object() {}
        inline std::unique_ptr<Object> clone() const
        {
            return std::unique_ptr<Object>(virtClone());
        }
    private:
        virtual Object* virtClone() const = 0;
    };
     
    class Tile : public Object
    {
    public:
        typedef Object typeParent; // lu par le code de ObjectFactory
        explicit Tile(int id) : _id(id) {}
        ~Tile() override {}
        inline std::unique_ptr<Tile> clone() const
        {
            return std::unique_ptr<Tile>(virtClone());
        }
        inline int getId() const {return _id;}
    private:
        Tile* virtClone() const override
        {
            return new Tile(*this);
        }
        int _id;
    };
     
    class TileDeriv : public Tile
    {
    public:
        typedef Tile typeParent; // lu par le code de ObjectFactory
        TileDeriv(int id, int idBis) : Tile(id), _idBis(idBis) {}
        ~TileDeriv() override {}
        inline std::unique_ptr<TileDeriv> clone() const
        {
            return std::unique_ptr<TileDeriv>(virtClone());
        }
        inline int getIdBis() const {return _idBis;}
    private:
        TileDeriv* virtClone() const override
        {
            return new TileDeriv(*this);
        }
        int _idBis;
    };
     
    template<class T>
    class ObjectFactory;
     
    template<>
    class ObjectFactory<Object> : public SingletonCRTP<ObjectFactory<Object>>
    {
        friend class SingletonCRTP<ObjectFactory<Object>>;
    private:
        ObjectFactory<Object>()  {}
        ~ObjectFactory<Object>() {}
    public:
        void add(std::string const& key, Object const& obj)
        {
            _mapFactory[key] = &obj;
        }
        std::unique_ptr<Object> construct(std::string const& key) const
        {
            Object const* tmp = _mapFactory.at(key);
            return tmp->clone();    
        }
    private:
        std::map<std::string, Object const*> _mapFactory;
    };
     
    template<class T>
    class ObjectFactory : public SingletonCRTP<ObjectFactory<T>>
    {
        friend class SingletonCRTP<ObjectFactory<T>>;
    private:
        ObjectFactory() : _objectFactoryParent(ObjectFactory<typename T::typeParent>::instance()) {}
        ~ObjectFactory() {}
    public:
        void add(std::string const& key, T const& specificObject)
        {
            _objectFactoryParent.add(key, specificObject);
            _mapFactory[key] = &specificObject;
        }
        std::unique_ptr<T> construct(std::string const& key) const
        {
            T const* tmp = _mapFactory.at(key);
            return tmp->clone();    
        }
    private:
        ObjectFactory<typename T::typeParent>& _objectFactoryParent;
        std::map<std::string, T const*>        _mapFactory;
    };
     
    int main()
    {
        ObjectFactory<Tile>&      tileFactory      = ObjectFactory<Tile>::instance();
        ObjectFactory<TileDeriv>& tileDerivFactory = ObjectFactory<TileDeriv>::instance();
        Tile      tile(1);
        TileDeriv tileDeriv(2, 3);
        tileFactory     .add("Tile 1",        tile);
        tileDerivFactory.add("TileDeriv 2-3", tileDeriv);
        std::unique_ptr<Tile>      toto = tileFactory     .construct("TileDeriv 2-3");
        std::unique_ptr<TileDeriv> titi = tileDerivFactory.construct("TileDeriv 2-3");
        std::cout << "Id de toto    : " << toto->getId()    << "\n";
        std::cout << "IdBis de titi : " << titi->getIdBis() << "\n";
        return 0;
    }

  5. #5
    Membre averti
    Homme Profil pro
    Analyse syst�me
    Inscrit en
    Novembre 2014
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Analyse syst�me

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par d�faut
    Ok merci j'ai r�ussi !

Discussions similaires

  1. design pattern factory
    Par olive_le_malin dans le forum C++
    R�ponses: 2
    Dernier message: 23/08/2007, 15h31
  2. Classe + design pattern factory
    Par Rodrigue dans le forum C++
    R�ponses: 8
    Dernier message: 07/11/2006, 14h42
  3. [Conception]Design Pattern Factory ?
    Par �om dans le forum Logging
    R�ponses: 8
    Dernier message: 13/09/2006, 10h20
  4. [Fabrique] [Java] Design Pattern Factory
    Par SkyBioSS dans le forum Design Patterns
    R�ponses: 3
    Dernier message: 24/05/2006, 14h53

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