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++ / Design Pattern Decorator] Comment garder les valeurs précédentes ?


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut [C++ / Design Pattern Decorator] Comment garder les valeurs précédentes ?
    Bonjour

    Pour mon application, qui sera un outil pour créer des personnages pour mon jeu, je fais appel au Design Pattern Decorator.
    En effet, un personnage peut être à la fois Guerrier et Sorcier.

    J'ai donc intégré, pour le moment, deux classes décoratrices : Guerrier et Sorcier.


    Pour tester l'architecture, dans mon main je lance tout d'abord la construction du personnage.
    Ensuite, je créé lui rajoute les caractéristiques du Guerrier, puis celles du Sorcier.
    Ce qui donne le code suivant :

    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
    #include <iostream>
     
    #include "Personnage.h"
    #include "Guerrier.h"
    #include "Sorcier.h"
     
     
    using namespace std;
     
    int main()
    {
        PersonnageBase* pb = new Personnage();
        cout << "pb : " << endl;
        cout << "Nom : " << pb->getNom() << endl;
        cout << "Endurance : " << pb->getEndurance() << endl;
        cout << "Force : " << pb->getForce() << endl << endl;
     
        pb = new Guerrier(*pb);
        pb->setClasse("Guerrier");
        cout << "Warrior : " << endl;
        cout << "Classe : " << pb->getClasse() << endl;
        cout << "Endurance : " << pb->getEndurance() << endl;
        cout << "Force : " << pb->getForce() << endl <<  endl;
     
        pb = new Sorcier(*pb);
        pb->setClasse("Sorcier");
        cout << "Warrior/Witch : " << endl;
        cout << "Classe : " << pb->getClasse() << endl;
        cout << "Endurance : " << pb->getEndurance() << endl;
        cout << "Force : " << pb->getForce() << endl << endl;
     
     
        return 0;
    }
    Le problème est le suivant : comment garder les caractéristiques du Guerrier, et lui ajouter celles du Sorcier ?

    Dès que je lui ajoute le décorateur Sorcier, les données sont remises à la valeur par défaut. Donc je perd tout ce que Guerrier avait ajouté au Personnage


    Merci d'avance

  2. #2
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    On ne peut pas répondre sans le code des classes guerrier et sorcier

  3. #3
    Invité
    Invité(e)
    Par défaut
    Au temps pour moi.

    Bon entre temps, j'ai réussi à ajouter les valeurs à l'objet de base. J'agis de la manière suivante (dans Sorcier pour l'exemple, Guerrier étant identique pour le moment) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "Sorcier.h"
     
    Sorcier::Sorcier(PersonnageBase& base) : PersonnageDecorator(base)
    {
        PersonnageBase::setClasse(getBase()->getClasse() + " Sorcier");
        PersonnageBase::setForce(getBase()->getForce() + 1);
        PersonnageBase::setEndurance(getBase()->getEndurance() + 2);
    }
     
    Sorcier::~Sorcier()
    {
        //dtor
    }
    Et le code de getBase() dans le Décorateur (seule fonction qu'il possède) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    PersonnageBase* PersonnageDecorator::getBase() const
    {
        return &m_base;
    }
    Donc en gros, je récupère l'objet de base passé en paramètre, et je lui ajoute mes données (si j'ai bien compris).

    Est-ce la bonne méthode ? Cela fonctionne, mais peut sûrement être optimisé.
    De plus, je ne comprend pas très bien pourquoi je dois appeler le setForce() et autres de la classe de base ?


    J'aurais plutôt fait comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Sorcier::Sorcier(PersonnageBase& base) : PersonnageDecorator(base)
    {
        getBase()->setClasse(getBase()->getClasse() + " Sorcier");
        getBase()->setForce(getBase()->getForce() + 1);
        getBase()->setEndurance(getBase()->getEndurance() + 2);
    }
    Merci d'éclairer ma (petite) lanterne ^^

  4. #4
    Membre régulier Avatar de cynique
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Points : 72
    Points
    72
    Par défaut
    Citation Envoyé par Furanku Voir le message
    Au temps pour moi.

    Bon entre temps, j'ai réussi à ajouter les valeurs à l'objet de base. J'agis de la manière suivante (dans Sorcier pour l'exemple, Guerrier étant identique pour le moment) :

    Et le code de getBase() dans le Décorateur (seule fonction qu'il possède) :
    Donc en gros, je récupère l'objet de base passé en paramètre, et je lui ajoute mes données (si j'ai bien compris).

    Est-ce la bonne méthode ? Cela fonctionne, mais peut sûrement être optimisé.
    De plus, je ne comprend pas très bien pourquoi je dois appeler le setForce() et autres de la classe de base ?


    J'aurais plutôt fait comme suit :
    Merci d'éclairer ma (petite) lanterne ^^
    D'accord. Un vrai Decorator doit faire un "override" du getClasse(), getForce(), et getEndurance(), et il ne doit pas modifier la classe de base.

    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 "Sorcier.h"
     
    Sorcier::Sorcier(PersonnageBase& base) : PersonnageDecorator(base)
    {
    }
     
    Sorcier::~Sorcier()
    {
        //dtor
    }
     
    int Sorcier::getForce()
    {
      return PersonnageDecorator::getForce()+1;
    }
     
    int Sorcier::getEndurance()
    {
      return PersonnageDecorator::getEndurance()+2;
    }
     
    std::string Sorcier::getClasse()
    {
      return PersonnageDecorator::getClasse()+" Sorcier";
    }
    Si le setForce( newForce ) de Sorcier doit accepter la Force totale au lieu de la Force de base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void Sorcier::setForce( int newForce )
    {
      PersonnageDecorator::setForce( newForce - 1 );
    }
     
    // etc.
    Si l'objet de "base", c-à-d l'objet decoré, est vraiment un Guerrier, tout marche bien, parce que le Sorcier ajoute pour chaque appel a getForce() son augmentation, après que le Guerrier ajoute la sienne.

  5. #5
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Pourquoi ne pas simplement passer par un héritage et une liste ?

    ce genre de chose:

    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
     
    #include <iostream>
    #include <list>
    #include <boost/shared_ptr.hpp>
     
    class Classe
    {
    public:
        //...
        virtual int getForce() const = 0;
    };
     
    class Sorcier : public Classe
    {
    public:
        //...
        int getForce() const
        {
            return -2;
        }
    };
     
    class Guerrier : public Classe
    {
    public:
        //...
        int getForce() const
        {
            return 3;
        }
    };
     
    class Personnage
    {
        typedef boost::shared_ptr< Classe > ClassPtr;
        std::list< ClassPtr > classes;
        //...
    public:
        int getForce() const
        {
            int ret = 0;
            for ( std::list< ClassPtr >::const_iterator it = classes.begin(); it != classes.end(); ++it )
                ret += (*it)->getForce();
            return ret;
        }
     
        template<class T>
        void addClasse( T& a )
        {
            classes.push_back( ClassPtr( new T(a) ) );
        }
    };
     
    int main()
    {
        Personnage perso;
        Guerrier guerrier;
        Sorcier sorcier;
     
        perso.addClasse( guerrier );
        perso.addClasse( sorcier );
     
        std::cout << perso.getForce() << std::endl;
        return 0;
    }
    Je ne dis pas que cette méthode est celle à suivre, mais je trouve que ça donne un code mieux encapsulé à savoir que chaque classe s'occupe de ce qu'elle doit faire.

    Ca m'intérresserait de connaître le pour et le contre =)

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 07/05/2009, 14h09
  2. Réponses: 1
    Dernier message: 04/06/2006, 01h35
  3. [Struts] Comment initialiser les valeurs d'un formulaire
    Par Sniper37 dans le forum Struts 1
    Réponses: 2
    Dernier message: 08/04/2005, 16h02
  4. Comment gérer les valeur Nulles dans une requête ?
    Par sondo dans le forum Bases de données
    Réponses: 3
    Dernier message: 16/03/2005, 12h02
  5. [Forms] Comment restreindre les valeurs d'une LOV
    Par popressay dans le forum Forms
    Réponses: 9
    Dernier message: 25/08/2004, 11h59

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