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 :

Recherche du bon design pattern (ou pas)


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 5
    Par défaut Recherche du bon design pattern (ou pas)
    Bonsoir à tous,

    voilà ma problématique :
    J'ai une classe mère M et plusieurs classes filles F1, F2, etc... Ces classes représentent les colonnes d'un tableau qui contient des types de données différents (double, string, etc..)

    Je récupère les données au fur et à mesure et je souhaite pouvoir modifier le type d'une colonne d'un type fille vers un autre type fille au fur et à mesure que j'analyse les données que je reçois. Si vous vous demandez "pourquoi ne pas le faire à la fin ?", la réponse est "pour gagner de l'espace mémoire", si je détecte qu'il s'agit d'entiers par exemple, je m'évite de les stocker sous forme de string.

    Bien sûr, la solution de base serait de créer à chaque fois une nouvelle instance fille du bon type, faire la copie puis supprimer l'ancienne... Néanmoins, c'est lourdingue et qui plus est, ce type de traitement doit être assez commun et j'ai l'impression qu'il doit surement y avoir un design pattern de derrière les fagots qui s'applique parfaitement à ce genre de problématique.

    Est-ce que quelqu'un a déjà été confronté à ce genre de problème ? Avez-vous des solutions ou des pistes à proposer ?

    Merci d'avance,

    d!

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour

    Un boost::variant (accepté pour C++17), associé au bon visteur, ne réglerait pas le souci ?

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 5
    Par défaut
    Merci pour cette réponse. Elle ne résout pas mon problème, mais elle pourrait m'aider pour la suite.

    En fait, je ne veux pas seulement traiter la donnée que je reçois à la volée mais aussi la stocker (et donc potentiellement la reconvertir à la volée par la suite).

    Un exemple :
    Pour ma première colonne je lis une chaine de caractères correspondant à un entier comme première valeur => Je crée un objet ColonneDEntier qui contient un vector<int> et qui a certaines propriétés
    Pareil pour les dix valeurs suivantes => je continue de stocker dans mon vecteur d'entiers
    A la 12eme valeur, j'ai un nombre flottant => je veux convertir mon objet ColonneDEntier en ColonneDeFlottant qui contient un vector<float> et des propriétés différentes.

    Je sais que je n'échapperai pas à la copie (avec conversion) du contenu de vector<int> dans vector<float>, mais j'aimerai m'éviter la construction/destruction d'objets ColonneDeXxxx. Etant donné que ma classe qui stocke l'ensemble contient un vector<Colonne> (classe mère), je voudrais éviter d'avoir à lui faire gérer plein de vérifications de types pour savoir quels sont les new spécifiques qu'il doit faire.

    Si je schématise l'algo, j'ai quelque chose dans ce goût la :

    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
     
    vector<Colonne *> monTableau;
     
    nbColonnes = lirePremierligne(); //La premiere ligne me permet juste de définir le nombre de colonnes, je ne traite pas son contenu
    monTableau.resize(nbColonnes);
    for (int i = 0; i < nbColonnes; ++i)
         monTableau[i] = new ColonneDeBooleens();   //J'initialise avec Booleen car c'est le type le plus restrictif dans mon cas
     
    lireChaqueLigne()
         pourChaqueValeurDeLaLigne()
              monTableau[i]->ajouteElement(valeur);  //La méthode ajoute élément vérifie si 'valeur' correspond bien au type courant de la colonne
     
              // Le cas échéant, je pourrais imaginer avoir ici quelque chose qui récupère le nouveau type et qui fait un truc du genre....
              switch (nouveauTypeColonne)
              {
                   case TypeTruc : ColonneDeTruc *nouvelleCol = new ColonneDeTruc(monTableau[i]); // Avec du coup, un constructeur par recopie de chaque type vers chaque type...
                        monTableau.remove(i);
                        monTableau.insert(i, nouvelleCol);
                        break;
                   case ... // Pareil pour chaque type
              }
              // ... Mais je voudrais éviter parce que je trouve ça crado... ^^
     
    Voilà, j'espère que c'est un peu plus clair.
     
    Merci pour vos réponses et suggestions. :)
     
    d!

  4. #4
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Tu lis une première ligne, qui te permet de déterminer le type de chaque colonne?
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2016
    Messages : 5
    Par défaut
    Citation Envoyé par dragonjoker59 Voir le message
    Tu lis une première ligne, qui te permet de déterminer le type de chaque colonne?
    Non, je choisi le type de façon arbitraire au départ.

  6. #6
    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
    C'est un exercice intéressant.

    Proposition :
    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
    class ColonneAbstraite
    {
    public:
        virtual ~ColonneAbstraite() {}
        virtual void ajouteElement(Tableau& parent, size_t indiceDeMoiMemeDansParent, const std::string& valeur) = 0;
            // Si la valeur n'a pas le bon type, créer une nouvelle colonne,
            // l'insérer dans le tableau à notre place et se suicider.
        // ...
    };
     
    class Tableau
    {
    private:
        std::vector<std::unique_ptr<ColonneAbstraite>> m_colonnes;
    public:
        std::unique_ptr<ColonneAbstraite> libererColonne(size_t indice) {
            assert(indice < m_colonnes.size());
            return std::move(m_colonnes[indice]);
        }
        void setColonne(size_t indiceColonne, std::unique_ptr<ColonneAbstraite> nouvelleColonne) {
            assert(indiceColonne < m_colonnes.size());
            m_colonnes[indiceColonne] = std::move(nouvelleColonne);
        }
        void ajouteElement(size_t indiceColonne, const std::string& valeur) {
            assert(indiceColonne < m_colonnes.size());
            m_colonnes[indiceColonne]->ajouteElement(*this, indiceColonne, valeur);
        }
        // ...
    };
     
    class ColonneChaines : public ColonneAbstraite { /* ... */ };
     
    class ColonneEntiers : public ColonneAbstraite { /* ... */ };
     
    class ColonneBooleens : public ColonneAbstraite
    {
    private:
        std::vector<bool> m_cellules;
    public:
        virtual ~ColonneBooleens() {}
        void ajouteElement(Tableau& parent, size_t indiceDeMoiMemeDansParent, const std::string& valeur) override
        {
            boost::optional<bool> valeurBooleenne = convertirEnBooleen(valeur);
            if(valeurBooleenne) {
                m_cellules.push_back(*valeurBooleenne);
            } else {
                std::unique_ptr<ColonneAbstraite> nouvelleColonne;
                boost::optional<int> valeurEntiere = convertirEnEntier(valeur);
                if(valeurEntiere) {
                    std::unique_ptr<ColonneEntiers> nouvelleColonneEntiers(new ColonneEntiers(*this));
                    nouvelleColonneEntiers->ajouterEntier(*valeurEntiere);
                    nouvelleColonne = std::move(nouvelleColonneEntiers);
                } else {
                    std::unique_ptr<ColonneChaines> nouvelleColonneChaines(new ColonneChaines(*this));
                    nouvelleColonneChaines->ajouterChaine(valeur);
                    nouvelleColonne = std::move(nouvelleColonneChaines);
                }
                std::unique_ptr<ColonneAbstraite> moi = parent.libererColonne(indiceDeMoiMemeDansParent);
                assert(moi.get() == this);
                parent.setColonne(indiceDeMoiMemeDansParent, std::move(nouvelleColonne));
            }
        }
        // ...
    };

Discussions similaires

  1. Le bon design pattern.
    Par Ali Kent dans le forum UML
    Réponses: 2
    Dernier message: 10/01/2015, 15h49
  2. [Couplage] Bon design pattern pour synchroniser deux modules (Adapter, Observer ?)
    Par Steph0 dans le forum Design Patterns
    Réponses: 2
    Dernier message: 21/06/2013, 14h16
  3. [PHP 5.1] A la recherche d'un design pattern
    Par Invité dans le forum Langage
    Réponses: 1
    Dernier message: 27/08/2010, 13h35
  4. [Composite] Recherche d'un design pattern proche
    Par telluri dans le forum Design Patterns
    Réponses: 7
    Dernier message: 03/04/2010, 17h21
  5. Design Pattern ou pas ?
    Par jc63 dans le forum Design Patterns
    Réponses: 3
    Dernier message: 13/08/2009, 23h22

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