1 / 61

Design patterns

Design patterns. Des modèles présentant des qualités particulières pour résoudre des problèmes fréquemment rencontrés en conception. Sommaire Qualités induites par les design patterns Utilisation des design patterns Classification des design patterns Des exemples de design patterns.

Download Presentation

Design patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Design patterns Des modèles présentant des qualités particulières pour résoudre des problèmes fréquemment rencontrés en conception Sommaire Qualités induites par les design patterns Utilisation des design patterns Classification des design patterns Des exemples de design patterns • Bibliographie • The Design Patterns, James W. Cooper, Addison Wesley, http://www.patterndepot.com/put/8/JavaPatterns.htm • Design Patterns, E. Gamma, R. Helm, R. Johnson, J. Vlissides, Addison-Wesley • Patterns in Java, Mark Grand, Wiley

  2. Qualités induites par les design patterns • la flexibilité • par implantation d'algorithmes interchangeables, strategy • par encapsulation de commandes, command • la réutilisabilité (par exemple, représentation des états d'un objet par des objets, mémento) • la manipulation aisée de grands nombres d'objets (par exemple, représentation d'un sous-système par un objet, facade) • la réutilisation • par adaptation d'interfaces, adapter • par composition, composite • l'indépendance avec les objets eux-mêmes (c'est-à-dire avec l'implémentation) en facilitant la manipulation d'interfaces (par exemple, builder)

  3. Qualités induites par les design patterns (fin) • la facilitation de la conception de structures complexes d'objets à l'exécution • l'augmentation de la robustesse des applications en permettant : • de créer un objet sans spécifier sa classe • d’encapsuler des messages dans des objets • d'éviter la dépendence matériel de l'application • de cacher l'utilisation d'objets dont la représentation est susceptible de changer • de cacher l'utilisation d'algorithmes susceptibles de changer • de cacher des classes fortement couplées pour obtenir un système faiblement couplé • d'effectuer une modification d'une classe dont on ne dispose pas du code source ou qui entraînerait la modification de plusieurs sous-classes

  4. Utilisation des design patterns • Pour la conception et la réalisation : • d'applications • de boite à outils (ensemble de classes réutilisables fournissant des services généraux, par exemple, un ensemble de classes pour gérer des listes, des piles, des tables,... • de frameworks (conception réutilisables de squelettes d'application personnalisables)

  5. Utilisation des design patterns (suite) Apports pour les applications • Les design patterns améliorent : • la réutilisation interne grâce à : • à l'isolation qui conduit à un faible couplage • la maintenabilité grâce à : • l'indépendance avec le matériel • l'isolation de sous-systèmes • l'extensibilité grâce à : • l'utilisation de la composition pour étendre la hiérarchie de classes • l'isolation de classes

  6. Utilisation des design patterns (suite) Apports pour les boites à outils • Les design patterns améliorent la facilité de réutilisation de code par l'augmentation de : • la flexibilité • l'applicabilité • l'efficacité

  7. Utilisation des design patterns (fin) Apports pour les frameworks • Un framework fournit l'architecture d'une application qui, elle, fournit le code des opérations. • Les design patterns améliorent la réutilisation de la conception par l'augmentation de : • la flexibilité • l'extensibilité • la documentation

  8. Des exemples de design patterns • Classification : • creational patterns • exemples :builder, singleton • structural patterns • exemples : adapter, composite, facade • behavioral patterns • exemples : command, iterator, memento, observer, strategy

  9. Des exemples de patterns • Builder • Sépare la construction d'un objet complexe de sa représentation • Singleton • Assure qu'une classe ne contient qu'une seule instance • Factory • Retourne une instance de la classe appropriée pour traiter les données fournies en paramètres • Template • Permet de définir un algorithme dans un classe et de laisser certains détails d'implémentation dans des sous-classes • Adapter • Convertit l'interface d'une classe existante en une autre interface

  10. Des exemples de patterns (suite) • Composite • Permet d'utiliser les composants d'un objet complexe de la même façon qu'on utilise l'objet complexe dans son ensemble • Facade • Permet d'utiliser les composants d'un objet complexe de la même façon qu'on utilise l'objet complexe dans son ensemble • Command • Encapsule des messages dans des objets de façon à contrôler leur séquencement, gérer une queue, défaire,… • Iterator • Moyen d’accès aux éléments d’un objet aggrégé indépendemment de l’objet lui-même • Memento • Capture et externalise l’état interne d’un objet de façon à pouvoir le restaurer

  11. Des exemples de patterns (fin) • Observer • Quand un objet change d’état, tous ses dépendants en sont notifiés et sont mis à jour • Strategy • Définit une famille d’algorithmes et permet à une application d’utiliser l’un ou l’autre algorithme indifféremment • Visitor • Crée des classes qui traitent d'un ensemble d' instances de manière spécifique

  12. Builder Sépare la construction d'un objet complexe de sa représentation Structure structure Director Builder 1..* construct ( ) buildPart ( ) for all structure structure.builPart () ConcreteBuilder buildPart () getResult () L'instance de la classe Director sera configurée de façon à être liée aux instances convenables de la classe ConcreteBuilder

  13. Builder (suite) Example : convertisseur de format RTF - ASCII RTF - LateX RTF - TexWidget ... Builders Director TextConverter static TextConverter getInstance(dest) convertCharacter (char) convertFontChange (font) convertParagraph () RTFReader parseRTF ( …) ASCIIConverter TeXConverter TextWidgetConverter convertCharacter (char) convertFontChange (font) convertParagraph () convertCharacter (char) convertFontChange (font) convertParagraph () convertCharacter (char) convertFontChange (font) convertParagraph () Selon la conversion à faire, l'objet RTFReader sera lié à l'objet ASCIIConverter ou bien à l'objet TeXConverter ou bien à l'objet TextWidgetConverter Il est aisée d'ajouter un nouveau format de conversion. Il suffit d'ajouter une nouvelle sous-classe de TextConverter et d'implémenter les opérations adéquates

  14. Builder (suite) • Java • class RTFReader { • void parseRTF (String mode, String Texte) • TextConverter converter=TextConverter.getInstance(mode); • ….. • converter.convertParagraph(); • ….. • converter.convertCharacter(); • ….. • converter.convertFontChange(); • ….. • } // fin de la methode parseRTF • } // fin de la classe RTFReader • abstract class TextConverter { • static TextConverter getInstance (String dest) { • switch (dest) { • case "ACSII" return new ACSIIConverter (); • case "TeX" return new TeXConverter (); • case "TWC" return new TeXWidgetConverter (); • default return null; • } // fin du switch • abstract void convertCharacter (char c) { • } // fin de la méthode • abstract void convertFontChange (font f) { • } // fin de la méthode • abstract void convertParagraph () { • } // fin de la méthode • } // fin de la classe TextConverter

  15. Builder (fin) • class ACSIIConverter extends TextConverter { • void convertCharacter (char c) { • …….. • } // fin de la méthode • void convertFontChange (font f) { • …….. • } // fin de la méthode • void convertParagraph () { • …….. • } // fin de la méthode • } // fin de la classe ASCIIConverter • class TeXConverter { • ….. • Class TeXWidgetConverter { • …..

  16. Singleton Assure qu'une classe ne contient qu'une seule instance Structure Singleton static uniqueInstance ... static Singleton Singleton () getSingleton () ... return uniqueInstance Le constructeur teste si uniqueInstance est vide. Si oui, il crée une instance, enregistre le pointeur vers cette instance dans uniqueInstance et retourne le contenu de uniqueInstance. Si une instance existe déjà, il retourne le contenu de uniqueInstance.

  17. Singleton (suite) Exemple : AudioClipManager AudioClip static uniqueInstance prevClip : AudioClip play () stop () audioClipManager () getAudioClipManager () play (AudioClip clip) stop () La classe AudioClipManager est un singleton. Elle s'assure qu'un seul clip est joué en même temps. L'opération play (AudioClip clip) teste si prevClip est vide. Si oui ,elle lance l'opération play sur le clip à jouer et met à jour prevClip Si non, elle stoppe l'instance de AudioClip référencée par prevClip, lance l'opération play () sur le nouveau clip à jouer et met à jour prevClip

  18. Singleton (fin) • Java • public class ClassPrincipale { • public static void main (String args[]){ • String commande="demarrage"; • while (commande!="") { • AudioClipManager manager=new AudioClipManager() ; • AudioClip clip=new AudioClip(commande); • manager.playClip(clip); • commande=readClavier() • } // fin du while • } // fin de l'opération main • private String readClavier () {…} • } // fin de classPrincipale • class AudioClipManager { • static AudioClipManager uniqueInstance=null; • AudioClip prevClip=null; • AudioClipManager AudioClipManager () { • if (uniqueInstance==null) { • uniqueInstance=this; • } // fin du if • return uniqueInstance; • } // fin du constructeur • public playClip (AudioClip clip) { • if (prevClip!=null) prevClip.stop(); • prevClip= clip; • prevClip.play(); • } // fin de l'opération playClip • } // fin de la classe AudioManager

  19. Factory Retourne une instance de la classe appropriée pour traiter les données fournies en paramètres Structure classe abstraite Factory namer (...) ClasseConcrète A ClasseConcrète B if (namer= ...) return new ClasseConcreteA(); else return new ClasseConcreteB() ;

  20. Factory (suite) Exemple : 1..* 1..* Livre titre résumé 1..* Factory Recherche FactoryRecherche définitRecherche () Vector livres Recherche () RechercheParTheme RechercheParAuteur RechercheParTheme () RechercheParAuteur () 1..* 1..* Auteur Thème String nomAuteur String theme getNomAuteur() retourneLivres() getTheme() retourneLivres()

  21. Factory (suite) classe Recherche { protected Vector livresRetournes=new Vector(); public Vector Recherche () { return livresRetournes; } // fin de la methode recherche } // fin de la classe Recherche class RechercheParAuteur extends Recherche { private Vector auteurs=new Vector(); public void ajoutAuteur (Auteur a) { auteurs.addElement(a); } // fin de la methode ajoutAuteur public RechercheParAuteur (String critère) { int i=0; while (auteurs(i).getNomAuteur()!=critere && i<auteurs.size()) { auteurs(i).getNomAuteur(); } // if (i<auteurs.size()){ livresRetournes=auteurs(i).retourneLivres(); } // fin de la methode recherche } // fin de la classe RechercheParAuteur class RechercheParTheme extends Recherche { private Vector themes=new Vector(); public void ajoutTheme (Theme t) {themes.addElement(a); } // fin de la methode ajoutTheme public RechercheParTheme (String critère) { int i=0; while (themes(i).getTheme()!=critere && i<themes.size()) { themes(i).getTheme(); } // fin du while if (i<themes.size()){ livresRetournes=themes(i).retourneLivres(); } // fin de la methode recherche } // fin de la classe RechercheParTheme

  22. Factory (fin) class FactoryRecherche { public Recherche definitRecherche (string type, string critere ) { if (type=="auteur") {return new RechercheParAuteur(critere);} else {return new RechercheParAuteur (critere);} } // fin de la methode definitRecherche } // fin de la classe factoryRecherche class application { public static void main (String args[]){ private string type=args(1); private string critere=args(2); protected Vector livres=new Vector(); FactoryRecherche f=new FactoryRecherche (); recherche r=f.definitRecherche (type, critere); livres=r.recherche(); for (i=0;i<livres.size();i++) { System.out.println (livres(i).getTitre)); } // fin du for } // fin du main } // fin de la classe application

  23. Template Permet de définir un algorithme dans un classe et de laisser certains détails d'implémentation dans des sous-classes classe abstraite SousClasse A SousClasse B

  24. Template (suite) Exemple : PageAccueil dessiner() PanelLogo() AccueilEntreprise AccueilEtudiant PanelMenu() PanelMenu()

  25. Template (suite) class Application { public static void main (String args[]){ private int statut=0; //affiche une fenetre de login ……… // recherche le login et récupère le statut de l'utilisateur ……… // si statut=1 il s'agit d'un etudiant, // si statut=2 c'est une entreprise if (statut==1) {AccueilEtudiant f= new AccueilEtudiant()} } if (statut==2) {AccueilEntreprise f=new AccueilEntreprise()} ……….. } // fin du main } // fin de la classe Application class PageAccueil extends Jframe { public PageAccueil() { // creation de la fenetre f ………… panelLogo(); panelMenu(f); //programmation des listeners ………. } // fin du constructeur public panelLogo() { /* creation d'un panel contenant le logo Dauphine et placement dans la fenetre f */ …………… } // fin de la methode panelLogo } // fin de la classe PageAccueil

  26. Template (fin) class AccueilEtudiant extends PageAccueil { public AccueilEtudiant() { super(); } // fin du constructeur public void panelMenu (PageAccueil f) { /*programmaton du menu etudiant et placement dans la fenetre passee en parametre*/ …… } // fin de la methode panelMenu } // fin de la classe AccueilEtudiant class AccueilEntreprise extends PageAccueil { public AccueilEntreprise() { super(); } // fin du constructeur public void panelMenu (PageAccueil f) { /*programmaton du menu entreprise et placement dans la fenetre passee en parametre*/ …… } // fin de la methode panelMenu } // fin de la classe AccueilEntreprise

  27. Adapter Convertit l'interface d'une classe existante en une autre interface Structure Target Adaptee request () specificRequest () Adapter request () adaptee.specificRequest () La classe existante Adaptee possède une opération specificRequest. Mais, l'application exécute l'opération request. Aussi La sous-classe Adapter de la classe Target implémente l'opération request de façon à cacher la vraie interface de la classe Adaptee.

  28. Adapter (suite) Exemple : Shape Textview boundingBox () getExtent () Line Text boundingBox () boundingBox () Textview.getExtent () Ce modèle permet à une application et la classe existante Textview de communiquer alors que ce n'était pas prévu. L'application appelle l'opération boundingBox sur un objet de la classe Text. Cette opération redirige l'appel en appellant l'opération getExtent sur l'objet de la classe Textview

  29. Adapter (fin) • Java • public class ClassPrincipale { • public static void main (String args[]){ • Shape monObjet=null; • …….. • monObjet = new Text (); • monObjet.boundingBox (); • } // fin de classPrincipale • interface Shape { • void boundingBox (); • } // fin de l'interface Shape • class Text implements Shape { • void boundingBox () • TextView t=new TextView (); • t.getExtent (); • ….. • } // fin de la méthode boundingBox • } // fin de la classe Text

  30. Composite Permet d'utiliser les composants d'un objet complexe de la même façon qu'on utilise l'objet complexe dans son ensemble Structure 1..* Component children getParent () ... Feuille Composite add (Component) remove (Component) getChild (Component) operation () ... operation () ... for all g in children g.operation () L'application exécute les mêmes opérations sur tous les composants qu'ils soient simples (Feuille) ou composés (Composite)

  31. Composite (suite) Exemple PlanningElement getDurée ():int getParent():Activite 1..* children Tâche getDurée():int Activité addChild (PlanningElement) removeChild (PlanningElement) getChild (int):PlanningElement getDurée ():int Jalon getDuree ():int ActivitéFormation ActivitéDéveloppement ActivitéOrganisation

  32. Composite (suite) • Java • abstract class PlanningElement { • Activite parent; • public Activite getParent() { • return parent; • } // fin de la methode getParent • public abstract getDuree () { • } // fin de la methode getDuree • } // fin de la classe PlanningElement • abstract class Activite extends PlanningElement { • private Vector children=new Vector (); • public PlanningElement getChild (int index) { • return (PlanningElement) children.elementAt(index); • } // fin de la méthode getChild • public void addChild (PlanningElement child) { • children.addElement (child); • child.parent=this; • } // fin de la methode addChild • public removeChild (PlanningElement child) { • children.removeElement(child); • } // fin de la methode removeChild • public int getDuree() { • int duree=0; • for (int i=0;i<children.size();i++) { • inc=children.elementAt(i).getDuree(); • duree+=inc; • } // fin du for • return duree; • } // fin de la methode getDuree • } // fin de la classe Activite

  33. Composite (fin) • public class Tacheextends PlanningElement { • int dateDebut=null; • int dateFin=null; • public Tache (int date1, int date2) { • dateDebut=date1; • dateFin=date2; • ........ • } // fin du constructeur • public int duree() { • return dateFin-dateDebut; • } // fin de la methode duree • } // fin de la classe Tache • public class Jalonextends PlanningElement { • int dateJalon=null; • public Jalon (int date1) { • dateJalon=date1; • ........ • } // fin du constructeur • public int duree() { • return 1; • } // fin de la methode duree • } // fin de la classe Jalon

  34. Facade Fournit une interface unique à l’ensemble des interfaces d’un sous-système de façon à réduire les communications entre sous-systèmes Facade • Facade connaît : • les classes du sous-système • délègue (après éventuelle transformation) les demandes de l’application aux “bons” objets du sous-système • Les classes du sous-système : • implémentent les fonctionnalités du sous-système • n’ont pas connaissance de la classe Facade

  35. Facade (suite) Exemple Application MessageFacade MessageFacade (String to, String from, String subject) setCorps (String messageBody) addAttachement (Object attach) setSignature (String sign) envoyer () Message String to String from String sujet Corps Attachement Signature EnvoiMessage 0..1 0..* 0..1 0..1 Pour créer un message puis l’envoyer, l’application crée un objet MessageFacade. Toutes les opérations exécutées par l’application le seront sur cet objet. Les classes et objets du sous-système sont complétement masqués à l’application

  36. Facade (suite) • Java • public class Application { • public void constitueMessage () • String to="etudiants"; • String from="MJ. Blin"; • String sujet="le pattern facade"; • MessageFacade message=new MessageFacade (to, from, sujet); • message.setCorps ("Pour créer un message puis l’envoyer, l’application crée un objet MessageFacade");message.setSignature("Marie-Jose Blin"); • message.envoyer(); • } // fin de la methode constitueMessage • } // fin de la casse Application • import systemeMessagerie.*; • public class MessageFacade { • Message monMes; • public MessageFacade (String to, String from, String sujet) { • monMes=new Message (to, from, sujet) • } // fin du constructeur • public setCorps (String messageBody) { • monMes.body=new Corps (messageBody); • } // fin de la methode setCorps • public setSignature(String signature) { • monMes.nom=new Signature(signature); • } // fin de la methode setSignature • public envoyer () { • monMes.envoi=new EnvoiMessage(monMes); • } // fin de la methode envoyer • } // fin de la classe MessageFacade

  37. Facade (fin) • package systemeMessagerie • class Message { • String to; • String from; • String sujet; • Corps body; • Signature nom; • EnvoiMessage envoi; • public Message (String a, String de, String pour) { • this.to=a; • this.from=de; • this.sujet=pour; • } // fin du constructeur • } // fin de la classe Message • class Corps { • String body; • public Corps (String c) { • body=c; • } // fin du constructeur • } // fin de la classe Corps • class Signature { • String nom; • public Signature (String s) { • nom=s; • } // fin du constructeur • } // fin de la classe Signature • class EnvoiMessage { • public EnvoiMessage (Message m) { • // constitution du protocole SMTP par consultation du message m • …….. • // envoi du message • …….. • } // fin du constructeur • } // fin de la classe EnvoiMessage

  38. Command Encapsule des messages dans des objets de façon à contrôler leur séquencement, gérer une queue, défaire,... Structure 1..* Application Invoker execute () Command 1..* Receiver action () receiver ConcreteCommand execute () receiver.action () L’application lie chaque objet Invoker à un objet ConcreteCommand. La classe ConcreteCommand implémente l’opération execute (). Cette opération lance l’opération action sur l’objet Receiver auquel il est lié. La classe Receiver implémente effectivement l’action. Elle appartient à l’application.

  39. Command (suite) Exemple Invoker Application execute () Command Fenetre Menu MenuItem 1..* add (MenuItem) clicked () Document open () close () cut () copy () paste () receiver PasteCommand ... execute () receiver.paste () ConcreteCommand Receiver Implantation des commandes de menu d’un éditeur de texte. Chaque objet MenuItem est lié à un objet ConcreteCommand (ici PasteCommand, …). Ces sous-classes implémentent l’opération exécute () en lançant l’opération correspondante sur l’objet Document lié.

  40. Command (suite) • Java • class Application extends Frame { • Document d=new Document(); • public static void main (String args[]) { • Menu itemAction=new Menu ("File"); • MenuItem subItemOpen = new CommandOpen(d); • itemAction.add(subItemOpen); • MenuItem subItemClose = new CommandClose(d); • itemAction.add(subItemClose); • ….. • subItemOpen.addActionListener (new Action()); • subItemClose.addActionListener (new Action()); • ….. • } // fin de la methode main • public Document getDocument() { • return d; • } // fin de la methode getDocument • public initDocument() { • d=null; • } // fin de la methode initDocument • class Action implements ActionListener { • public void ActionPerformed (ActionEvent e) { • Command cmd=(Command) e.getSource(); • cmd.execute(); • } // fin de la methode ActionPerformed • } // fin de la classe Action • } // fin de la classe Application

  41. Command (fin) • interface Command { • public void execute() {} • } // fin de l'interface Command • class CommandeOpen extends MenuItem implements Command { • Document monDocument=null; • public CommandeOpen (Document d) { • super("open"); • monDocument=d; • } // fin du constructeur • public void execute () { • monDocument.open(); • } // fin de la methode Execute • } // fin de la classe CommandeOpen • class CommandeClose extends MenuItem implements Command { • Document monDocument=null; • public CommandeClose (Document d) { • super("close"); • monDocument=d; • } // fin du constructeur • public void execute () { • monDocument.close(); • } // fin de la methode Execute • } // fin de la classe CommandeClose

  42. Iterator Moyen d’accès aux éléments d’un objet aggrégé indépendemment de l’objet lui-même Structure 1..* 1..* Aggregate Application Iterator createIterator () first () next () isDone () currentItem () ConcreteAggregate createIterator () 1..* ConcreteIterator return new ConcretIterator (this) Plusieurs objet ConcreteIterator peuvent être associés au même objet ConcreteAggregate si on veut parcourir l’objet aggrégé de différentes façons

  43. Iterator (suite) Exemple Aggregate 1..* 1..* AbstractList Iterator Application createIterator () count () append (Item) remove (Item) ... first () next () isDone () currentItem () FilteredList FilteringIterator ConcreteAggregate ConcreteIterator SkipList SkipListIterator ConcreteAggregate ConcreteIterator Deux classes de listes sont définies : FilteredList et SkipList. Chaque liste créée est associée à un objet Iterator appartenant à la classe correspondante au moyen d’accès approprié.

  44. Iterator (suite) • Java • public class Application { • public void gereListe () { • FilteredList maListe=new FilteredList(); • Iterator it=(Iterator) maListe.createIterator(); • ….. • Item i=it.first() • Item i=it.next(); • Item i=it.currentItem(); • boolean fin=it.isDone(); • ….. • } // fin de la methode gereListe • } // fin de la classe Application • public interface Iterator { • public Item first (); • public Item next (); • public boolean isDone (); • public Item currentItem (); • } // fin de l'interface Iterator • public interface AbstractList { • public Iterator createIterator (); • public int count (); • public void append (Item i); • public void remove (Item i); • } // fin de l'interface AbstractList

  45. Iterator (fin) • public class FilteredList implements AbstractList { • ….. • public Iterator createIterator () { • return new FilteringIterator(); • } // fin de la methode createIterator • ... • } // fin de la classe FilteredList • class FilteringIterator implements Iterator { • public Item first() { • ….. • } // fin de la methode first • public Item next() { • ….. • } // fin de la methode next • public boolean isDone() { • ….. • } // fin de la methode isDone • public Item currentItem() { • ….. • } // fin de la methode currentItem • } // fin de la classe FilteringIterator

  46. Memento (ou Snapshot ou State) Capture et externalise l’état interne d’un objet de façon à pouvoir le restaurer Structure : Memento Originator CareTaker state state getState () setState () setMemento (Memento m) createMemento () return new Memento (state) state=m.getState() aCareTaker aMemento anOriginator createMemento () new Memento setState () setMemento (aMemento) getState ()

  47. Memento (suite) Exemple : Originator CareTaker ElementGraphique Memento Action xDebut yDebut xFin yFin couleur xDebut yDebut xFin yFin couleur deplace (ElementGrahique, real, real) changeDimension ( ElementGraphique, real, real, real, real) changeCouleur( ElementGraphique, Couleur) defaire (ElementGraphique) setMemento (Memento) createMemento ():Memento dessine () getState () setState () Rectangle Cercle Ligne Les opérations déplace, changeCouleur et changeDimension de l’objet Action suscite la création d’un objet Mémento de façon à conserver l’état de l’élément graphique avant l’exécution de l’action. L’opération défaire peut ainsi faire reprendre à l’élémentGraphique son état antérieur. Comme tous les états antérieurs sont conservés systématiquement, toutes les actions effectuées peuvent être ainsi défaites successivement.

  48. Memento (suite) • Java • class Action { • private Vector states=new Vector(); • void deplace (ElementGraphique e, real x, real y) { • sauveEtat(e); • e.setxDebut(x); • e.setyDebut(y); • // recalcul de xFin et de yFin • ..... • e.dessine(); • } // fin de la methode deplace • void changeDimension (ElementGraphique e, real x1, • real y1, real x2, real y2) { • sauveEtat(); • e.setxDebut(x1); • e.setyDebut(y1); • e.setxFin(x2); • e.setyFin(y2); • e.dessine(); • } // fin de la methode changeDimension • void changeCouleur (ElementGraphique e, Color c) { • sauveEtat(); • e.setCouleur(c); • e.dessine(); • } // fin de la methode deplace • void defaire (ElementGraphique e) { • int nbreEtats=states.size(); • Memento s= state.elementAt(nbreEtats-1); • states.removeElement(nbreEtats-1); • e.setMemento(s); • e.dessine(); • } // fin de la methode defaire • void sauveEtat (ElementGraphique e) { • Memento s=e.createMemento(); • states.addElement (s); • } // fin de la methode sauveEtat • } // fin de la classe Action

  49. Class ElementGraphique { • ..... • Memento createMemento () { • Memento m=new Memento () • m.setState(this); • return m; • } // fin de la methode createMemento • void setMemento (Memento m) { • Vector v=m.getStates(); • xDebut=v.elementAt(0); • yDebut=v.elementAt(1); • xFin=v.elementAt(2); • yFin=v.elementAt(3); • couleur=v.elementAt(4); • } // fin de la methode setMemento • void setxDebut (real x) { • xDebut=x; • } // fin de la methode setxDebut • ….. • } // fin de la classe ElementGraphique • class Memento { • Vector state=new Vector(); • void setState(ElementGraphique e) { • state(0)=e.getxDebut(); • state(1)=e.getyDebut(); • state(2)=e.getxFin(); • state(3)=e.getyFin(); • state(4)=e.getCouleur(); • } // fin de la methode setState • Vector getState () { • return state; • } // fin de la methode getState • } // fin de la classe Memento

  50. Observer Quand un objet change d’état, tous ses dépendants en sont notifiés et sont mis à jour Structure 1..* Subject Observer subject observer attach (Observer) detach (Observer) notify () update () for all o in observer o.update () ConcreteObserver observertState ConcreteSubject update () subjectState return subjectState getState () setState () observerState = subject.getState () Chaque objet ConcreteSubject peut être associé à plusieurs objets ConcreteObserver. Quand il change d’état, son opération “notify” lance l’opération “update” sur tous ses objets associés qui se mettent alors à jour.

More Related