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 :

Utilisation judicieuse du design pattern Factory


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 96
    Points : 47
    Points
    47
    Par défaut Utilisation judicieuse du design pattern Factory
    Bonjour,

    Je suis en train de créer un petit moteur physique 2D.
    L'objet World contient donc une collection d'objets.
    Les objets contiennent eux une collection de de primitives géométriques (rectangles, cercles, etc).

    Il me semble que la création/gestion d'objet devient vite fastidieuse.

    Est-il judicieux dans ce cas, d'utiliser un design pattern Factory ? Pour avoir simplement à "demander" un nouvel objet et ainsi masquer toute la gestion new/delete.
    Mais aussi pour enregistrer un objet complexe et ne pas avoir à recalculer toutes les normales par exemple.

    Pour avoir un code utilisateur genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int main(int argc, char* argv[])
    {
       CShape shape;
       shape    << CVector(0,0)
                    << CVector(0,10)
                    << CVector(10,10)
                    << CVector(10,0);
       CWorld::register("monRectangle", shape);
       CObject* object = CWorld::create("monRectangle");
     
       return 0;
    }
    L'usage d'un singleton est-il justifié ?

    Merci

  2. #2
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Agoudard Voir le message
    Est-il judicieux dans ce cas, d'utiliser un design pattern Factory ?
    Oui

    Citation Envoyé par Agoudard Voir le message
    L'usage d'un singleton est-il justifié ?
    Non

  3. #3
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    +1

    Une chose judicieuse est le Data-Driven programming.
    Homer J. Simpson


  4. #4
    screetch
    Invité(e)
    Par défaut
    le singleton n'est jamais justifié (si c'est un mensonge, c'est beaucoup plus proche de la vérité que "le singleton est souvent une bonne idée)

    /me en croisade contre les singletons

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 96
    Points : 47
    Points
    47
    Par défaut
    Ok, donc quelque chose qui ressemble à :

    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
     
    int main(int argc, char* argv[])
    {
       CWorld world;
     
       // Enregistrement de l'objet monRectangle
       CShape shape;
       shape << CVector(0,0)
                 << CVector(0,10)
                 << CVector(10,10)
                 << CVector(10,0);
       world.getObjectFactory().register("monRectangle", shape);
     
       // Création de l'objet monRectangle & ajout à world
       CObject* object = world.getObjectFactory().create("monRectangle");
     
       return 0;
    }
    est un code assez confortable et opaque ?

    Autre question : C'est mieux si CShape est un builder non ?

    Merci pour vos réponses.

  6. #6
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Bonjour,

    CWorld se comporte comme une fabrique un peu particulière dans la mesure où elle se base sur un prototype pour créer l'instance. Son gros défaut est qu'elle ne te permet pas de passer les paramètres de construction.

    CShape se comporte en effet comme un builder. Le fait est que CShape ne sait pas ce qu'il construit. Tu peux recourir à une approche du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CShapeBuilder builder;
    builder.beginRectangle();
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.endRectangle();
    En fonction du besoin, tu peux ajouter des niveaux d'abstraction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CShapeBuilder builder;
    builder.begin("Rectangle");
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.addVector( Vector(0.0,1.0) );
    builder.end("Rectangle");
    Mais là, tu sens bien que ça complexifie. Il faut que le CShapeBuilder fasse appel lui même à des builders. Du coup tu vas introduire un CRectangleBuilder et ajouter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CWorld::getShapeBuilder()
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CWorldRegisterShapeBuilder( builderName, concreteBuilder )
    Puis, tu vas te dire : Mais pourquoi ne pas faire un CVectorBuilder... Alors, tu vas l'introduire et au final : Tu auras une architecture in-buvable, ré-utilisable à souhait mais donc les 3/4 sera utilisé une et une seule fois.

    Tout ça pour dire : A quoi bon ajouter ces niveaux d'abstractions si le besoin n'est pas là? As-tu besoins de créer des instances en fonction d'une chaine de caractères représentant le nom de la classe?


    Si je peux me permettre un conseil : Il faut partir de tes besoins pour former ton architecture, plus que d'essayer de caser tous les design patterns de l'univers.

    "Keep it Simple, Stupid". Commence par une architecture triviale en te laissant suffisamment de porte ouverte pour la modifier (refactoring).

    (Les fabriques échappent un peu à la règle dans la mesure où il n'est pas aisé de refactorer les new sans produire un "break change")

    Cdlt

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 96
    Points : 47
    Points
    47
    Par défaut
    Il faut partir de tes besoins pour former ton architecture, plus que d'essayer de caser tous les design patterns de l'univers.
    , je programme pour me familiariser avec les bonnes pratiques de programmation puisque je ne suis pas un professionnel mais un étudiant. Il ne s'agit même pas d'un exercice de fac.
    Donc j'essaye de produire un code standard et réutilisable.

    Le gros problème c'est qu'effectivement en voulant rendre générique réutilisable optimisé, etc... Je fais que lire de la doc et je programme jamais. Ou alors je passe plusieurs heures sur un détail.

    Donc je suis tombé d'accord avec moi même (c'est déjà pas mal), et pour le coup je cherche à faire quelque chose de facile à utiliser.

    Donc le moins de new/delete possible.
    Le moins d'objet possible à manipuler.

    D'où ma question, quelqu'un voit-il des améliorations quant à la facilité d'utilisation ?

  8. #8
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Ok

    Citation Envoyé par Agoudard Voir le message
    D'où ma question, quelqu'un voit-il des améliorations quant à la facilité d'utilisation ?
    Justement oui :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CRectangle rec(0.0,1.0,0.0,1.0);
    plus simple que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    //
    CObjectFactory objectFactory;
    CRectangle* rect = objectFactory.createRectangle(0.0,1.0,0.0,1.0);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //
    CRectangle* rect = world.getObjectFactory().createRectangle(0.0,1.0,0.0,1.0);
    plus simple que ta proposition

    Le gros problème c'est qu'effectivement en voulant rendre générique réutilisable optimisé, etc...
    On ne peut pas avoir le tout, donc c'est bien que tu aies fixé des priorités. Mais là, tu ne crois pas que tu vises surtout la généricité?

    ps :

    Voici peut être une lecture qui t'intéressera (de longue haleine). Ca traite des bonnes pratiques de conception d'une part, mais aussi de ce qui guide les choix de conception :
    "Microsoft Application Architecture Guide, 2nd Edition" (voir sur google), et en particulier le chapitre "Software Architecture and Design"

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 96
    Points : 47
    Points
    47
    Par défaut
    Merci

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Je ne suis par contre pas persuadé du bien fondé de l'idée qui consiste à placer une fabrique dans le monde, et encore moins de celle qui consiste à placer un accesseur dessus

    En effet, si je suis tout à fait d'accord avec le fait que le singleton est souvent un fausse bonne idée, world ne devrait pas grand chose à voir avec ce qui permet de construire le contenu de world

    La fabrique pourrait, éventuellement, connaitre world, de manière à être en mesure d'enregistrer les éléments (et encore), mais il n'y a, a priori, aucune raison pour que world connaisse la fabrique.

    La raison principale est que, bien souvent, ce ne sera pas world qui construira ce qui le compose.

    Pire encore, il est plus que vraisemblable que les systèmes permettant de créer le contenu de world viennent à se multiplier:

    Il est parfaitement envisageable que tu crées, pour commencer, un système utilisant des entrées utilisateur (clavier ou souris) pour créer le contenu de world, mais qu'il soit rapidement suivi par un système de (dé)sérialisation, afin d'être en mesure de récupérer ce qui a été envisagé "par ailleurs".

    L'ordre de création pourrait donc etre proche 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
    int main()
    {
        /* le monde */
        CWorld world;
        /* la fabrique, qui "remplis" le monde */
        CFactory factory;
        /* l'objet responsanble du chargment (d'un fichier, ou d'un flux
         * quelconque
         */
        CLoader reader("file.ext");
        /* chargement du monde */
        reader.load(factory, world);
        /* l'exécution du monde */
        world.run();
        return 0;
    }
    (nota: load prendrait une référence (constante) sur factory et une référence non constante sur world )
    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

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 96
    Points : 47
    Points
    47
    Par défaut
    Ok, merci.

    On peut pas juste pour commencer, enregistrer le CWorld dans la fabrique et s'assurer que les objets soient stockés dans CWorld ?

    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
     
    int main()
    {
        /* le monde */
        CWorld world;
        /* la fabrique, qui "remplis" le monde */
        CFactory factory;
        /* Visibilité du monde par la fabrique */
        factory.addWorld(world);
     
        /* Enregistrement d'un objet, création et initialisation*/
        ...
        factory.addPattern("maForme", shape);
        CObject* object = factory.create("maForme");
        object.setVelocity(CVector(10, 10));
        object.setAngularVelocity(3.1415);
     
        /* Calculer à une date t+dt */
        world.dt(100);
     
        return 0;
    }

  12. #12
    Membre expérimenté

    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
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Passe world au constructeur de la factory dans ce cas.

    MAT.

  13. #13
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait CLoader est à considérer, par exemple, comme un système de (dé)sérialisation, qui serait capable de récupérer les informations nécessaires depuis un flux quelconque

    C'était une manière de bien faire comprendre que chaque responsabilité mérite d'être clairement établie et distinguée:
    • La fabrique... fabrique les objets
    • Le monde les utilise
    • "Quelque chose" les enregistre et les charge (ou s'occupe de la récupération des données qui permettront de fabriquer les objets par un moyen quelconque )
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 24/02/2009, 12h06
  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. [GRASP] Est-ce que j'utilise correctement les design pattern?
    Par Tourix dans le forum Design Patterns
    Réponses: 7
    Dernier message: 21/06/2006, 18h27
  5. [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