Patrons de conception/État
La technique de l'État est un patron de conception comportemental utilisé en génie logiciel.
Ce patron de conception est utilisé entre autres lorsqu'il est souhaité pouvoir changer le comportement de l'État d'un objet sans pour autant en changer l'instance.
Principe Général.
La classe censée changer d'état a un lien vers une classe abstraite "État".
Cette classe abstraite "État" définit les différentes méthodes qui seront à redéfinir dans les implémentations.
Dans chaque classe dérivée d'État, l'appel à la méthode X pourra avoir un comportement différent.
La classe pouvant changer d'état appellera les services de sa classe d'état dont l'instance change quand le comportement de notre classe change.
De plus l'instance de la classe pouvant changer d'état peut être passée en paramètre à la méthode X de sa classe d'état.
Ceci permet de changer l'état de la classe pendant l'exécution de la méthode X en instanciant un nouvel état. 
Ce patron permet donc à la classe de passer d'un état à l'autre de telle façon que cette dernière apparaît changer de type dynamiquement (sans changer d'instance).
Exemple : Un programme de dessin utilise une interface abstraite pour représenter un outil.
Chaque instance de ses classes dérivées concrètes représente un type d'outil différent.
Quand l'utilisateur change d'outil, une nouvelle instance de la classe dérivée associée est créée.
Diagramme de classes.
Le patron de conception État peut être représenté par le diagramme de classes UML suivant :
La classe Contexte utilise différentes instances des classes concrètes dérivées de la classe abstraite État afin de représenter ses différents états.
Chaque état concret traite la requête de manière différente.
Exemples.
C++.
En reprenant l'exemple du programme de dessin :
class AbstractTool
public:
 virtual void MoveTo(const Point& inP) = 0;
 virtual void MouseDown(const Point& inP) = 0;
 virtual void MouseUp(const Point& inP) = 0;
Chaque outil a besoin de gérer les évènement de souris : déplacement, bouton enfoncé, bouton relâché.
L'outil plume est alors le suivant :
class PenTool : public AbstractTool
public:
 virtual void MoveTo(const Point& inP)
 if(mMouseIsDown)
 DrawLine(mLastP, inP);
 mLastP = inP;
 virtual void MouseDown(const Point& inP)
 mMouseIsDown = true;
 mLastP = inP;
 virtual void MouseUp(const Point& inP)
 mMouseIsDown = false;
private:
 bool mMouseIsDown;
 Point mLastP;
class SelectionTool : public AbstractTool
public:
 virtual void MoveTo(const Point& inP)
 if(mMouseIsDown)
 mSelection.Set(mLastP, inP);
 virtual void MouseDown(const Point& inP)
 mMouseIsDown = true;
 mLastP = inP;
 mSelection.Set(mLastP, inP);
 virtual void MouseUp(const Point& inP)
 mMouseIsDown = false;
private:
 bool mMouseIsDown;
 Point mLastP;
 Rectangle mSelection;
Une classe utilisant le patron d'état ci-dessus :
class DrawingController
public:
 DrawingController() { selectPenTool(); } // Démarrer avec un outil.
 void selectPenTool()
 currentTool.reset(new PenTool);
 void selectSelectionTool()
 currentTool.reset(new SelectionTool);
private:
 std::auto_ptr<AbstractTool> currentTool;
L'état de l'outil de dessin est complètement représenté par une instance de la classe AbstractTool.
Cela facilite l'ajout de nouveaux outils et conserve leur comportement dans les sous-classes de la classe AbstractTool.
Contre-exemple utilisant switch.
Le patron de conception peut être utilisé pour remplacer des instructions codice_1 et codice_2, qui peuvent être difficile à maintenir et moins typées.
L'exemple suivant est similaire au précédent, mais ajouter un nouvel outil dans cette version est beaucoup plus difficile.
class Tool
public:
 virtual void MoveTo(const Point& inP);
 virtual void MouseDown(const Point& inP);
 virtual void MouseUp(const Point& inP);
private:
 enum Mode { Pen, Selection };
 Mode mMode;
 Point mLastP;
 bool mMouseIsDown;
 Rectangle mSelection;
void Tool::MoveTo(const Point& inP)
 switch(mMode)
 case Pen:
 if (mMouseIsDown)
 DrawLine(mLastP, inP);
 mLastP = inP;
 break;
 case Selection:
 if (mMouseIsDown)
 mSelection.Set(mLastP, inP);
 break;
 default:
 throw std::exception();
void Tool::MouseDown(const Point& inP)
 switch(mMode)
 case Pen:
 mMouseIsDown = true;
 mLastP = inP;
 break;
 case Selection:
 mMouseIsDown = true;
 mLastP = inP;
 mSelection.Set(mLastP, inP);
 break;
 default:
 throw std::exception();
void Tool::MouseUp(const Point& inP)
 mMouseIsDown = false;