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 :

Drole de fabrique


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut Drole de fabrique
    Bonjour à tous,

    Je travaille actuellement sur une grosse lib de traitement d'images, qui repose entièrement sur le pattern fabrique. En fait, tous les objets sont instanciés à partir d'un fichier xml de configuration contenant le nom des classes à utiliser (c'est d'ailleurs un peu perturbant comme système).
    J'avais l'habitude de voir les fabriques sous la forme d'une classe de base offrant la fonction virtuelle clone(), avec insertion d'un objet de chaque classe dans une map<string,ClassPrototype*>.
    Cette lib offre un mécanisme un peu particulier basé sur les macro : toutes les classes utilisent la macro suivante dans leur déclaration:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #define DECLARE_CLASS( __NAME__) \
          static ObjectInterface* create() \
             {\
                     return new __NAME__(); \
            }
    Une autre macro , REGISTER_CLASS(MaClasse):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define REGISTER_CLASS(__NAME__) \
    ObjectInterfaceFactory::instance().registerObject(QString(#__NAME__),__NAME__::create);
    permet d'enregistrer la classe dans ce qui semble être une map<string, pointeur de fonction >

    Il semble que l'utilité du système soit d'éviter l'instantiation d'un objet de chaque type (vu le nombre de classe, ça se justifie). Cette utilisation de la fabrique est-elle courante (Je l'ai également vu dans wxWidget) et pose-elle des problèmes de conception majeurs (faut aimer les macros)?

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    C'est très courant, et c'est même une meilleure solution car pour créer de nouveaux objets, on utilise une fonction plutôt qu'une instance bidon.

    Par contre l'intégration à base de macros n'est pas terrible, on peut faire ça beaucoup plus proprement.

  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 Laurent Gomila Voir le message
    C'est très courant, et c'est même une meilleure solution car pour créer de nouveaux objets, on utilise une fonction plutôt qu'une instance bidon.
    Si tu as des termes à donner pour effectuer une recherche sur Google, je suis preneur.
    Je rame, en ce moment... J'ai mis mon map en statique, et ça ne veut pas linker.

  4. #4
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    Effectivement, s'il existe une solution simple sans macro (je vois pas bien comment s'en passer à par en insérant directement le code remplacé par leur utilisation ), je suis preneur^^

  5. #5
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    e rame, en ce moment... J'ai mis mon map en statique, et ça ne veut pas linker.
    Dans mon exemple la map est stockée en statique également (enfin je crois). T'es sur de l'avoir bien redéclaré dans le cpp?

  6. #6
    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
    Et non... J'avais tellement la tête dans le guidon, et comme cette fabrique a présenté toute une série de problème, je ne me suis même pas posé la question de ce truc aussi simple. Je pensais que ça venait forcément de nouveaux territoires conceptuels que j'explorais !

    Relis mes post dans la section C++ et C++/Boost, et si tu veux t'inspirer de ce sur quoi je suis parti et que tu as besoin d'explications, n'hésite pas.
    Le seul truc qui me chagrine, c'est le transtypage explicite lors de l'ajout dans le map, et que je n'avais pas eu à faire quand j'ai fait un bout de code simpliste hors classe pour expérimenter ma fabrique.

  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 vikki Voir le message
    permet d'enregistrer la classe dans ce qui semble être une map<string, pointeur de fonction >
    C'est exactement ce que je cherche présentement à faire, mais sans macro !
    Voir mes posts des derniers jours, si ça t'intéresse.

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Citation Envoyé par vikki Voir le message
    J'avais l'habitude de voir les fabriques sous la forme d'une classe de base offrant la fonction virtuelle clone(), avec insertion d'un objet de chaque classe dans une map<string,ClassPrototype*>.
    Ca ressemble au design pattern prototype ça plutôt qu'à fabrique abstraite.

    MAT.

  9. #9
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Oui mais un type de fabrique utilise aussi le pattern prototype pour instancer...
    Voir ICI.

  10. #10
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par Laurent Gomila
    C'est très courant, et c'est même une meilleure solution car pour créer de nouveaux objets, on utilise une fonction plutôt qu'une instance bidon.

    Par contre l'intégration à base de macros n'est pas terrible, on peut faire ça beaucoup plus proprement.
    Laurent, pourrais-tu développer un peu?
    Concrêtement, comment s'affranchir des macros? C'est ce que j'utilise jusqu'à maintenant, alors si je peux faire mieux !

    Voici un aperçu du code que j'utilise : une factory dans un singleton, une classe descriptor qui est ma classe de base principale...
    Une définition de macro me sert à "register" mes fonctions de création.
    Le dernier exemple de code montre comment je l' implémente dans une classe concrète.

    Factory :
    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 OBJECT_FACTORY_H
    #define OBJECT_FACTORY_H
     
    #include <map>
    #include <boost/noncopyable.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/function.hpp>
    #include <string>
     
    template <typename T>
    class object_factory : private boost::noncopyable
    {
    public:
     
    	static object_factory& instance()
    	{
    		static object_factory<T> instance;
    		return instance;
    	}
     
    	void register_object(const std::string& str, boost::function<boost::shared_ptr<T>(void)> func)
    	{
    		m_map[str] = func;
    	}
     
    	boost::shared_ptr<T> create(const std::string& str)
    	{
    		return m_map[str]();
    	}
     
    private:
    	object_factory() {}
    	std::map<std::string,  boost::function<boost::shared_ptr<T>(void)> > m_map;
    };
     
    #endif
    Classe de base: Descriptor
    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
     
    #ifndef DESCRIPTOR_H
    #define DESCRIPTOR_H
     
    #define DECLARE_CLASS( __NAME__) \
    	static boost::shared_ptr<descriptor> create() \
    {\
    	return boost::shared_ptr<descriptor>(new __NAME__());  \
    }
     
    #define REGISTER_CLASS(__NAME__) \
    	object_factory<descriptor>::instance().register_object(#__NAME__, __NAME__::create);
     
    class descriptor
    {
    public:
    	descriptor() {}
    	virtual ~descriptor() {}
    };
     
     
    #endif
    Classe concrète :
    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 DESCRIPTOR_SHAPE_H
    #define DESCRIPTOR_SHAPE_H
     
    #include "Descriptor.h"
    #include "Point.h"
    #include <vector>
     
    class descriptor_shape : public descriptor
    {
    public:
    	DECLARE_CLASS(descriptor_shape)
    	descriptor_shape()
    	{
    		REGISTER_CLASS(descriptor_shape)
    	}
     
    	std::pair<Point<double>, Point<double>> m_Rect;
    };

Discussions similaires

  1. Fabriquer des requêtes sql à partir d'un document xml
    Par ktel dans le forum XQUERY/SGBD
    Réponses: 4
    Dernier message: 18/10/2005, 16h45
  2. Mon PC fait un drole de bruit que faire
    Par maceo dans le forum Composants
    Réponses: 6
    Dernier message: 09/05/2005, 22h02
  3. [GOF] Fabrique abstraite peut-elle être un Singleton ?
    Par manel007 dans le forum Design Patterns
    Réponses: 7
    Dernier message: 06/01/2005, 10h02
  4. [GOF] [Fabrique Abstraite] [Pont] Questions ?
    Par manel007 dans le forum Design Patterns
    Réponses: 5
    Dernier message: 04/01/2005, 20h18
  5. fabriquer un .X
    Par Fikus dans le forum DirectX
    Réponses: 4
    Dernier message: 23/03/2004, 15h24

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