Le pattern State

Principes
Structure
Collaboration
Conséquences
Implentation
Code
Utilisations
Patterns Apparentés
Retour d'expérience
Conclusion

Retour en haut de la page...

Principes

Ce pattern est à utiliser lorsque l'on souhaite modifier dynamiquement le comportement d'un objet quand son état interne change.

Il permet de remplacer des déclarations conditionnelles (if imbriqués) dans les opérations (méthodes), éventuellement basées sur des enum (états) identiques dans des opérations distinctes.

 

Retour en haut de la page...

Structure


Architecture du pattern State

Retour en haut de la page...

Collaboration

Context délègue les requêtes à son _state (concret) courant.

Ces requêtes peuvent éventuellement prendre en paramètre la référence sur le contexte (_etat->handle(*this)), pour deux raisons possibles :

L'utilisateur accède au context (qui joue le rôle d'interface), mais jamais aux états (dont il n'a pas connaissance).

La responsabilité de modifier l'état courant est :

 

Retour en haut de la page...

Conséquences

Le pattern isole les comportements spécifiques d'états et partitionne les différents comportements.

Il rend les transitions d'état plus explicites, et plus nettes (étant donné que la granularité est le State, il n'existe pas d'état transitoire constitué de plusieurs variables non entièrement affectées): un état correspond à une instance, et non pas à n variables internes.

Les objets State peuvent être partagés si il n'y a pas de variables d'instances (Cf. Pattern "Poids Mouche"): cela pourra éventuellement orienter l'implentation.

Retour en haut de la page...

Implentation

Qui définit les transitions d'état?

Alternative à cette première solution: transitions pilotées par table (Se référer au livre).

Compromis sur la durée de vie des ConcreteState: faut-il les créer/détruire à chaque utilisation ou une unique fois?

A chaque utilisation :

Tout créer au début et tout détruire à la fin:

Il faut donc faire un compromis entre le coût mémoire, et le coût d'instanciation.

Utilisation de l'héritage dynamique: impossible en C++ (Se référer au livre).

Retour en haut de la page...

Code

State implente le comportement par défaut de toutes les requêtes qui lui sont déléguées.

La classe State est déclarée "friend" de Context pour accéder facilement le méthode privée Contexte::changeState(State&) (comme State::changeState(Contexte&, State&) )

Chaque ConcretState est un Singleton (pas besoin de conserver des références sur les ConcretState)

Chaque requête d'un ConcretState se termine par changeState(Contexte&, ConcreteStateXXX::instance())

Retour en haut de la page...

Utilisations

 

Retour en haut de la page...

Patterns Apparentés

Le Poid Mouche, pour savoir quand et comment partager les objets State.

Le Singleton : les objets State sont souvent des Singleton.

Retour en haut de la page...

Retour d'expérience

Question: Les méthodes de State sont elles virtuelles pures ?
Réponse: Oui.

 

Retour en haut de la page...

Conclusion

Etant donné la forte dépendance des classes entre elles, voire des classes imbriquées, l'implentation de ce pattern est difficilement réutilisable.

 

03/11/2001

www.2ia.net © 2001-2004