Pattern État PowerPoint 2003, télécharger la visionneuse PowerPoint Viewer dernière édition si vous ne lavez pas…télécharger la visionneuse PowerPoint Viewer dernière édition si vous ne lavez pas…
EtatConcret Chaque sous-classe implémente un comportement associé avec létat de contexte. Définition : Le pattern état permet à un objet de modifier son comportement quand son état interne change. Tout se passera comme si lobjet changeait de classe. > Etat +méthode1() +méthode2() +méthode3() +méthode4() EtatConcret +méthode1() +méthode2() +méthode3() +méthode4() EtatConcret +méthode1() +méthode2() +méthode3() +méthode4() EtatConcret +méthode1() +méthode2() +méthode3() +méthode4() EtatConcret +méthode1() +méthode2() +méthode3() +méthode4() Contexte +méthode1() +méthode2() +méthode3() +méthode4() Contexte - Définit linterface intéressant les clients. - Gère une instance dune sous-classe EtatConcret qui définit létat en cours. Etat -Définit une interface qui encapsule le comportement associé avec un état en particulier de contexte.
Machine à bonbons
Pas de pièce A une pièce Bonbon vendu Plus de bonbons Remplir Insérer pièce éjecter pièce Tourner poignée délivrer bonbon Bonbon > 0 Bonbon = 0
Une méthode par action Variable dinstance détat courant Voici les 4 états Constructeur Bloc conditionnelle servant à tester les états Public class Distributeur { final static int EPUISE = 0; final static int SANS_PIECE = 1; final static int A_PIECE = 2; final static int VENDU = 3; int etat = EPUISE; int nombre = 0; public Distributeur (int nombre) { this.nombre = nombre; if (nombre > 0) { etat = SANS_PIECE; } public void insererPiece() { if (etat == A_PIECE) { System.out.println("Vous ne pouvez plus inséré de pièces"); } else if (etat == SANS_PIECE) { etat = A_PIECE; System.out.println("Vous avez inséré une pièce"); } else if (etat == EPUISE) { System.out.println("Rupture de stock, ne pas insérer de pièce"); } else if (etat == VENDU) { System.out.println(« Veuillez patienter, le bonbon va tomber"); } public void ejecterPiece() { …… } public void tournerPoignee() { …… } public void delivrer() { …… } … }
Public class TestDisributeur { public static void main (String[ ] args) { Distributeur distributeur = new Distributeur(5); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.ejecterPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.ejecterPiece(); %java TestDistributeur Vous avez inséré une pièce Vous avez tourné… Un bonbon va sortir… System.out.println(distributeur); Stock 5 bonbons Lappareil attend une pièce Stock 4 bonbons Lappareil attend une pièce Vous avez inséré une pièce Pièce retournée Vous avez tourné mais il ny a pas de pièce Il faut payer dabord Stock 4 bonbons Lappareil attend une pièce Vous avez inséré une pièce Vous avez tourné... Un bonbon va sortir... Vous avez inséré une pièce Vous avez tourné... Un bonbon va sortir... Vous n'avez pas inséré de pièce Stock 2 bonbons Lappareil attend une pièce …
Public class TestDisributeur { public static void main (String[ ] args) { Distributeur distributeur = new Distributeur(5); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.ejecterPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.ejecterPiece(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); distributeur.insererPiece(); distributeur.tournerPoignee(); Vous avez inséré une pièce Vous ne pouvez pas insérer d'autres pièces Vous avez tourné... Un bonbon va sortir... Vous avez inséré une pièce Vous avez tourné... Un bonbon va sortir... Aïe, plus de bonbons ! Vous ne pouvez pas insérer de pièce, nous sommes en rupture de stock Vous avez tourné, mais il n'y a pas de bonbons Pas de bonbon délivré System.out.println(distributeur); Stock 2 bonbons Lappareil attend une pièce Stock 0 bonbons Lappareil est en rupture de stock …
Indication dutilisation Le comportement dun objet dépend de son état, et ce changement de comportement doit intervenir dynamiquement Les opérations comportent de grand pans entiers de déclarations conditionnelles en fonctions de létats de lobjet. Cet état est généralement désigné par une ou plusieurs constantes dénumération. Souvent, plusieurs opérations différentes, contiendront la même structure conditionnelle. public void insererPiece() { if (etat == A_PIECE) { … } else if (etat == SANS_PIECE) { … } else if (etat == EPUISE) { … } else if (etat == VENDU) { … } public void ejecterPiece() { if (etat == A_PIECE) { … } else if (etat == SANS_PIECE) { … } else if (etat == EPUISE) { … } else if (etat == VENDU) { … } public void tournerPoignee() { if (etat == A_PIECE) { … } else if (etat == SANS_PIECE) { … } else if (etat == EPUISE) { … } else if (etat == VENDU) { … } Le modèle état place dans une classe séparée, chacune des branches de la condition. Ceci permet de traiter létat de lobjet, comme un objet à part entière, qui peut varier indépendamment des autres objets. Public class etatPiece { … }Public class etatEpuiser { … }Public class etatVendu { … }Public class etatSensPiece { … } Public interface etat { … }
> public interface Etat { public void insererPiece(); public void ejecterPiece(); public void tournerPoignee(); public void delivrer(); } public class EtatAPiece implements Etat { Distributeur distributeur public EtatAPiece(Distributeur distributeur) { this.distributeur = distributeur; } public void insererPiece() { System.out.println("Vous ne pouvez pas insérer d'autre pièce"); } public void ejecterPiece() { System.out.println("Pièce retournée"); distributeur.setEtat(distributeur.getEtatSansPiece()); } public void tournerPoignee() { System.out.println("Vous avez tourné..."); distributeur.setEtat(distributeur.getEtatVendu()); } public void delivrer() { System.out.println("Pas de bonbon délivré"); } public class EtatEpuise implements Etat { Distributeur distributeur; public EtatEpuise(Distributeur distributeur) { this.distributeur = distributeur; } public void insererPiece() { System.out.println("Vous ne pouvez pas insérer de pièce, nous sommes en rupture de stock"); } public void ejecterPiece() { System.out.println("Ejection impossible, vous n'avez pas inséré de pièce"); } public void tournerPoignee() { System.out.println("Vous avez tourné, mais il n'y a pas de bonbons"); } public void delivrer() { System.out.println("Pas de bonbon délivré"); } Implémentation de linterface Etat et des classes EtatConcret
Distributeur insererPiece() ejecterPiece() tournerPoignee() remplir(…) setEtat(…) liberer() … EtatEpuise insererPiece() ejecterPiece() tournerPoignee() delivrer() EtatSansPiece insererPiece() ejecterPiece() tournerPoignee() delivrer() EtatAPiece insererPiece() ejecterPiece() tournerPoignee() delivrer() EtatVendu insererPiece() ejecterPiece() tournerPoignee() delivrer() > Etat insererPiece() ejecterPiece() tournerPoignee() delivrer()
Transformation de la classe Distributeur Public class Distributeur { final static int EPUISE = 0; final static int SANS_PIECE = 1; final static int A_PIECE = 2; final static int VENDU = 3; int etat = EPUISE; int nombre = 0; public Distributeur (int nombre) { this.nombre = nombre; if (nombre > 0) { etat = SANS_PIECE; } } public class Distributeur { Etat etatEpuise; Etat etatSansPiece; Etat etatAPiece; Etat etatVendu; Etat etat = etatEpuise; int nombre = 0; public Distributeur(int nombreBonbons) { etatEpuise = new EtatEpuise(this); etatSansPiece = new EtatSansPiece(this); etatAPiece = new EtatAPiece(this); etatVendu = new EtatVendu(this); this.nombre = nombreBonbons; if (nombreBonbons > 0) { etat = etatSansPiece; } Lobjet distributeur crée les objets état et les instancie dans son constructeur, puis la variable etat contiendra une référence vers létat dorigine, soit SansPiece, soit Epuiser, suivant quil est rempli ou vide Etats du Distributeur Sans Piece APiece Vendu Epuiser Distributeur.etat
public void insererPiece() { etat.insererPiece(); } public void ejecterPiece() { etat.ejecterPiece(); } public void tournerPoignee() { etat.tournerPoignee(); etat.delivrer(); } void setEtat(Etat etat) { this.etat = etat; } public Etat getEtatSansPiece() { return this.etatSansPiece; } public Etat getEtatVendu() { return this.etatVendu; } public Etat getEtatAPiece() { return this.etatAPiece; } public Etat getEtatEpuise() { return this.etatEpuise; } public int getNombre() { return this.nombre; } public String toString() { return "\nDistribonbon, SARL.\n Distributeur compatible Java, modèle 2007 \n Stock "+ nombre +" bonbons \n"+ ((nombre > 0)? "L'appareil attand une piece\n": "L'appareil est en rupture de stock\n") ; void liberer() { System.out.println("Un Bonbon va sortir..."); if (nombre != 0) { nombre = nombre -1; } Void remplir(int nombre) { this.nombre = nombre; etat = etatSansPiece; } On remarque que le contexte, ici le distributeur, Peut aussi changer son état. => Létat peut être changé soit : -D-Dans les états concrets - Dans le contexte
public void tournerPoignee() { etat.tournerPoignee(); etat.delivrer(); } Etats du Distributeur SansPiece APiece Vendu Epuiser tournerPoignee() etatAPiece public void tournerPoignee() { System.out.println("Vous avez tourné..."); distributeur.setEtat(distributeur.getEtatVendu()); } Vous avez tourné… Un bonbon va sortir etatVendu public void delivrer() { distributeur.liberer(); if (distributeur.getNombre() > 0) { distributeur.setEtat(distributeur.getEtatSansPiece()); } else { System.out.println("Ae, plus de bonbons !"); distributeur.setEtat(distributeur.getEtatEpuise()); } etat tournerPoignee() Delivrer() Nombre = 5Nombre = 4 Distributeur
- rend le code plus lisible car il enlève les grandes déclarations de type conditionnel qui ne sont pas souhaitables car elles ont un éffet monolithique qui à tendance à rendre le code moins explicite - rend les transitions détat plus explicite car il introduit des objets distincts pour chaque état
Exemple prit dans le livre : Voir le site Tête la premièreVoir le site Tête la première OU voir le site OReillyvoir le site OReilly