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 :

[conception] pattern state


Sujet :

C++

  1. #1
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut [conception] pattern state
    Bonjour,

    voil�, je vois partout le pattern state impl�ment� ainsi:
    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
    class AbstractState {
    public:
       virtual void DoSomething() = 0;
    };
     
    class ConcreteState1 : public AbstractState {
    public:
       void DoSomething() { /* implémentation */ }
    };
     
    class ConcreteState2 : public AbstractState {
    public:
       void DoSomething() { /* implémentation */ }
    };
     
    class MyObject {
    private:
       AbstractState * m_state;
     
    public:
       void ChangeState( AbstractState * newState ) { 
    	   delete m_state; 
    	   m_state = newState; 
       }
     
       void DoSomething() { m_state->DoSomething(); }
    };
    Seulement, dans certains cas cette fa�on de faire ne me convient pas, � cause du fait que quand on change d'�tat (fonction ChangeState dans mon exemple), il faut allouer un nouvel �tat et d�sallouer l'ancien. C'est un cas que j'ai rencontr� r�cemment qui m'a fait penser � cela: une classe qui change souvent d'�tat, et dont les �tats poss�dent des donn�es => beaucoup d'allocation/d�sallocations qui, de plus, sont co�teuses.

    Du coup, j'ai modifi� le pattern comme ceci:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // les classes AbstractState et ConcreteStateN ne changent pas
     
    class MyObject {
    private:
    	AbstractState * m_state;
    	ConcreteState1 m_state1;
    	ConcreteState2 m_state2;
     
    public:
    	void GoToState1() { m_state = &m_state1; }
    	void GoToState2() { m_state = &m_state2; }
     
    	void DoSomething() { m_state->DoSomething(); }
    };
    Seulement, je n'ai vu cette impl�mentation nulle part. Et pourtant je lis beaucoup de code ces derniers temps. Je me demande donc s'il n'y aurait pas un probl�me que je n'ai pas vu et qui fait ce ma m�thode est tr�s mauvaise.

    Voil�, donc c'est pour savoir: qu'en pensez-vous?

  2. #2
    screetch
    Invit�(e)
    Par d�faut
    Il n'y a aucun probl�me avec ca et c'est comme ca que chacun devrait faire a mon avis =)
    [EDIT] parler sans reflechir c'est mal... ca consomme plus de m�moire comme ca.
    Derni�re modification par screetch ; 18/02/2009 � 17h59.

  3. #3
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Je ne connais pas cette fa�on de faire. Quand j'ai besoin d'une machine � �tat, j'en suis rest� � la bonne vieille m�thode avec une matrice d'�tats/transitions (sauf si le nombre d'�tats devient trop grand, auquel cas la matrice se transforme en fonction avec switch et if imbriqu�s).

    J'imagine que le b�n�fice de coder comme �a, c'est que tu peux rajouter des �tats sans toucher au code de ta classe MyObject (je n'en vois pas d'autres, et je vois plut�t plein d'inconv�nients). L�, en mettant des membres dans ta classe, tu perds ce b�n�fice. Du coup, autant revenir � la matrice d'�tats/transitions

  4. #4
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    En cherchant un peu sur le net, j'ai trouv� quelques conseils sur le pattern state qui peuvent r�pondre en partie � ta question :
    1/ Un �tat ne devrait pas contenir de variables membres : seul le comportement change,
    2/ Les �tats devraient �tre des singletons (en coh�rence avec pr�c�dent) : ce qui �vite ces allocations/destructions r�p�titives.

    Dans ton exemple, le probl�me que je vois, c'est que d�s que tu auras un certaine nombre d'�tat tu vas �tre tent� de refaire un switch pour positionner ton �tat courant...

  5. #5
    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
    Quand tu instancies MyObject, il faut que tu initialises tous les �tats. Apr�s j'ai envie de dire, �a d�pend combien tu as d'�tats et surtout est-ce que tu vas tous les "utiliser" plusieurs fois (plusieurs boucles en fait)?
    Il faut quand m�me t'assurer que c'est moins co�teux comme �a...

    Si c'est pour tourner "longtemps", alors oui dans ton impl�mentation tu vas consommer plus de m�moire, mais tu iras plus vite!

  6. #6
    Alp
    Alp est d�connect�
    Expert confirm�

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 36
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par d�faut
    A part � rendre �a un peu plus g�n�rique, je pense que c'est pas mal

  7. #7
    screetch
    Invit�(e)
    Par d�faut
    au pire du pire, avec une tonne de m�ta prog et une lisibilit� r�duite, tu peux avoir un buffer contenant assez de place pour le plus gros des �tats et faire un placement new.
    tes �tats contiennent ils des variables ?

  8. #8
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    Ben en fait je parlais du cas g�n�ral.

    Donc si je fais une synth�se de ce qui a �t� dit:
    avantages de cette m�thode:
    - cette m�thode permet de gagner en rapidit� d'ex�cution dans le cas o� les �tats continennent des donn�es (m�me si c'est d�conseill�, �a peut �tre pratique).

    d�savantages de cette m�thode:
    - si on ajoute un �tat, on doit rajouter une fonction membre + une variable membre (le nouvel �tat) et son initialisation � la construction de l'objet.
    - si on a beaucoup d'�tat, le code peut devenir tr�s lourd

    conclusion: bien quand on a pas beaucoup d'�tats.

    �tes-vous d'accord?

  9. #9
    screetch
    Invit�(e)
    Par d�faut
    Si tu as beaucoup de ces machines a �tat tu risques de consommer beaucoup plus de m�moire. tes �tats p�sent tous au moins 4 octets (la table de m�thodes virtuelles)

  10. #10
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    J'ai vraiment du mal avec cette id�e de mettre des variables dans une classe �tat.

    L'�tat d'une machine � �tat, c'est l'union de la valeur de tous ses membres. Autrement dit, tout ce qui caract�rise l'�tat de la machine, doit �tre dans la classe machine.

    Sinon, je vois une grosse diff�rence s�mantique entre ce que tu fais et l'impl�mentation initiale :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    void ChangeState( AbstractState * newState ) { 
               delete m_state; 
               m_state = newState; 
       }
    m_state est � priori un �tat nouvellement cr�� (je vois mal comment faire autrement).

    Tandis que :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
     void GoToState1() { m_state = &m_state1; }
    m_state est un ancien �tat, qu'on ressuscite, mais donc, avec ses anciens membres.

    Ce qui fait que l'�tat de ta machine est tr�s largement complexifi�, puisque l'�tat actuel est aussi d�pendant de ton historique, et d'�tats non courant.

    Honn�tement, je ne vois pas comment on peut faire un minimum de preuve de fonctionnement (ce qui est quand m�me l'int�r�t d'une machine � �tats) l� dessus.

  11. #11
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    Citation Envoy� par white_tentacle Voir le message
    J'ai vraiment du mal avec cette id�e de mettre des variables dans une classe �tat.
    L'id�e du pattern state c'est de d�l�guer des fonction � la classe �tat.

    Prenons un exemple: ma classe Objet a une fonction LogState(); qui doit �crire de fa�on "humainement lisible" son �tat courant dans un logger. Et bien la classe State aura besoin d'une instance, ou d'un lien quelconque (r�f�rence, pointeur, que sais-je encore) vers le logger en question. On aura donc bien besoin d'une variable pour cela.

    Citation Envoy� par white_tentacle Voir le message
    Honn�tement, je ne vois pas comment on peut faire un minimum de preuve de fonctionnement (ce qui est quand m�me l'int�r�t d'une machine � �tats) l� dessus.
    En faisant comme ceci par exemple:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     void GoToState1() 
    { 
       m_state = &m_state1; 
       m_state->Init();
    }

  12. #12
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    Citation Envoy� par r0d Voir le message
    L'id�e du pattern state c'est de d�l�guer des fonction � la classe �tat.

    Prenons un exemple: ma classe Objet a une fonction LogState(); qui doit �crire de fa�on "humainement lisible" son �tat courant dans un logger. Et bien la classe State aura besoin d'une instance, ou d'un lien quelconque (r�f�rence, pointeur, que sais-je encore) vers le logger en question. On aura donc bien besoin d'une variable pour cela.
    Une std::string ne poss�de pas une r�f�rence vers un flux pour �crire sa valeur... Le principe est le m�me ici. Ton �tat doit pouvoir se logger dans un logger qui lui est fourni.
    En fait, � chaque �tat, ce que tu change, ce sont les comportements et pas les donn�es qui caract�risent ton �tat. C'est pourquoi les variables dans les �tats c'est d�routant.

    Citation Envoy� par r0d Voir le message
    En faisant comme ceci par exemple:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     void GoToState1() 
    { 
       m_state = &m_state1; 
       m_state->Init();
    }
    En r�alit�, tu devrais plut�t appel� explicitement le destructeur et faire un placement new. Mais, mon sentiment est que �a devient de la bidouille.

  13. #13
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    Citation Envoy� par 3DArchi Voir le message
    Une std::string ne poss�de pas une r�f�rence vers un flux pour �crire sa valeur... Le principe est le m�me ici. Ton �tat doit pouvoir se logger dans un logger qui lui est fourni.
    En fait, � chaque �tat, ce que tu change, ce sont les comportements et pas les donn�es qui caract�risent ton �tat. C'est pourquoi les variables dans les �tats c'est d�routant.


    En r�alit�, tu devrais plut�t appel� explicitement le destructeur et faire un placement new. Mais, mon sentiment est que �a devient de la bidouille.
    Ok si tu veux. C'�tait un mauvais exemple. Mais il y a des cas o� c'est vraiment pratique. Peut-�tre �vitable, mais pratique. Par exemple une machine de vente de boissons: quand elle sera en �tat "rendre la monnaie", il y aura plein de trucs qu'elle devra savoir dont elle n'aura pas besoin dans l'�tat "encaisser", comme par exemple la monnaie qu'elle a en r�serve.

    Citation Envoy� par 3DArchi Voir le message
    En r�alit�, tu devrais plut�t appel� explicitement le destructeur et faire un placement new. Mais, mon sentiment est que �a devient de la bidouille.
    C'est jsutement ce que je cherche � �viter: appeler le destructeur (et donc le constructeur apr�s).

  14. #14
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    Citation Envoy� par r0d Voir le message
    C'est jsutement ce que je cherche � �viter: appeler le destructeur (et donc le constructeur apr�s).
    Soit Init fait la m�me chose que le destructeur et le constructeur, soit il ne fait pas la m�me chose. Dans ce dernier cas, cela veut dire que ton �tat conserve une 'm�moire', donc ce n'est plus tout � fait le m�me �tat...

  15. #15
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    Il peut faire la m�me chose sans r�allouer. Juste initialiser les variables membres. En plus, ainsi on peut se permettre de n'initialiser que celles qui ont besoin de l'�tre, c'est toujours �a de pris.

  16. #16
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    L'appel explicite au destructeur suivi du placement new ne fait pas d'allocation/lib�ration mais se contente ... d'appeler le destructeur puis le constructeur.

  17. #17
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    Citation Envoy� par 3DArchi Voir le message
    En cherchant un peu sur le net, j'ai trouv� quelques conseils sur le pattern state qui peuvent r�pondre en partie � ta question :
    1/ Un �tat ne devrait pas contenir de variables membres : seul le comportement change,
    2/ Les �tats devraient �tre des singletons (en coh�rence avec pr�c�dent) : ce qui �vite ces allocations/destructions r�p�titives.
    Yop,

    tu saurais retrouver l'endroit o� tu as lu �a? J'ai pas mal cherch� mais je ne trouve rien de tel :/

  18. #18
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    Citation Envoy� par r0d Voir le message
    Yop,

    tu saurais retrouver l'endroit o� tu as lu �a? J'ai pas mal cherch� mais je ne trouve rien de tel :/
    Non
    Sinon, il y a le tutoriel sur le pattern Etat de Pierre Caboche

  19. #19
    r0d
    r0d est d�connect�
    Membre exp�riment�

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    4 301
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 4 301
    Billets dans le blog
    2
    Par d�faut
    okay merci

  20. #20
    yan
    yan est d�connect�
    R�dacteur
    Avatar de yan
    Homme Profil pro
    Ing�nieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activit� : Ing�nieur expert
    Secteur : High Tech - Multim�dia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par d�faut
    Salut,
    Ce qu'on fait Qt est assez sympa:
    http://qt.developpez.com/doc/4.6-sna...temachine-api/

    Ce que j'aime bien :
    * on peut �viter de faire une classe pour chaque �tat
    * on peut tous modifier dynamiquement et utiliser SCXML
    * l'utilisation du syt�me de signal/slot qui permet de ne pas avoir de fonction DoSomething dans la classe �tats et qui permet de modifier dynamiquement le fonctionnement.

    Boost a s�rement quelque chose de similaire.

Discussions similaires

  1. cas d'�tude: pattern state
    Par r0d dans le forum C++
    R�ponses: 33
    Dernier message: 11/10/2013, 13h46
  2. R�ponses: 0
    Dernier message: 04/02/2013, 14h45
  3. Combinaison de plusieurs etats avec le pattern State
    Par papaetoo dans le forum Design Patterns
    R�ponses: 0
    Dernier message: 18/08/2009, 11h16
  4. [DESIGN J2ME] Utilisation du pattern STATE ?
    Par BerBiX dans le forum Java ME
    R�ponses: 0
    Dernier message: 04/12/2008, 15h55

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