5. Introduction aux Design Patterns Les Patterns GRASS General ResponsabilityAssignement Software Patterns
6.
7.
8.
9.
10.
11.
12.
13.
14. Principes fondamentaux de conception Ouverture-Fermeture OCP Inversion des dépendances DIP Substitution de Liskov LSP Séparation des interfaces ISP
15.
16.
17.
18.
19.
20.
21.
22. Principes de substitution de LISkOV ( LSP ) : exemple class Rectangle { int longueur, largeur; public: virtual void setValeur(int long, int larg) {longueur = long; largeur = larg; }; class Carre : public Rectangle { public: virtual void setValeur(int long, int larg) { if (long != larg) throw std::exception(« long !=larg"); super.setValeur(long, larg); } }; void utiliserRectangle(int lng) { leRectangle.setValeur(lng, lng * 2); assert(leRectangle.getArea() == (length*length*2)); Que se passe-t-il si le Rectangle est un carré? Héritage<>Composition
35. UP & les modèles UML (2) Modèle des cas d’utilisation Expose les cas d’utilisation et leurs relations avec les utilisateurs Modèle d’analyse Détaille les cas d’utilisation et procède à une première répartition du comportement du système entre divers objets Modèle de conception Définit la structure statique du système sous forme de sous système, classes et interfaces ; Définit les cas d’utilisation réalisés sous forme de collaborations entre les sous systèmes les classes et les interfaces Modèle d’implémentation Intègre les composants (code source) et la correspondance entre les classes et les composants Modèle de test Décrit les cas de test vérifiant les cas d’utilisation Modèle de déploiement Définit les nœuds physiques des ordinateurs et l’affectation de ces composants sur ces nœuds. Modèle d'architecture Description de l’architecture (réutilisable)
101. Observer : Java setChanged () {changed = true;} NotifyObservers() { if (changed) { for each observer update(); changed = false; } Cela permet d'optimiser en n'appelant pas les observers à chaque changement d'état du sujet,mais seulement après un setChanged(). import java.util.*;
102. Observer : Java- Swing Public class Exemple{ JFrame cadre; Public static main(){ Exemple e = new Exemple(); e.go();} Public void go(){ cadre =new JFrame(); Jbutton b = new Jbutton (« Dois-je le faire »); b.AddActionListener(new Ange()); b.AddActionListener(new Demon()); ………………………………… .} } class Ange implements ActionListener { Public void ActionPerformed(ActionEvent e) {Print « Non »}} class Ange implements ActionListener { Public void ActionPerformed(ActionEvent e) {Print « Oui »}} Dois-je le faire Non Oui
103. Observer : Exercice1 Mer-Montagne Meteo.Calculer met température entre 0 et 20. Skieur.update va en vacances si la température est < 10° Nageur.update va en vacances si la température est >= 10° Meteo m = new Meteo(); Nageur n = new Nageur(); Skieur s =new Skieur(); m.addObserver(n); m.addObserver(s); m.calculer(); m.setChanged(); m.calculer(); m.setChanged(); m.calculer(); m.setChanged(); m.calculer(); le skieur va a la montagne : 8 le nageur va a la mer : 12 le skieur va a la montagne : 6 8 8 12 ? Observable -changed: bool +addObserver(Observer) +deleteObserver(Observer) +countObservers(): int +deleteObservers() +notifyObservers() #setChanged() Observer Meteo -temperature: int +setChanged() +calculer() +getTemperature(): int Skieur +update(p1: Observable, p2: Object) Nageur +update(p1: Observable, p2: Object) Main +main(args: String)
107. Visiteur et l’objet Composite Iterator iter =employees.iterator(); { Employee e; while (iter.hasNext()) { e =(Employee)iter.next(); e.Accept(visitor);} } RMQ : Il est possible d’explorer l’ensemble d’un composite avec un visiteur. Dans ce cas Employee et Employees ont tous les deux une méthode Accept et sont donc des Elements.
110. Mémento : UML La classe à surveiller-----La mémoire----Le programme client (main) UnDo-ReDo
111.
112. Mémento : Exemple(1) import java.util.*; // "Originator" class SalesProspect { private String name; private String phone; private double budget; public String getName() { return name; } public void setName(String value) { name = value; } public String getPhone() { return phone; } public void setPhone (String value) { phone = value; } public double getBudget() { return budget; } public void setBudget (double value) { budget = value; } public Memento SaveMemento() {return (new Memento( name, phone, budget ));} public void RestoreMemento( Memento memento ) { this.name = memento.getName(); this.phone = memento.getPhone(); this.budget = memento.getBudget(); } public void Afficher() { System.out.println( "Sales prospect ---- " ); System.out.println( "Name: " + this.name ); System.out.println( "Phone: " + this.phone ); System.out.println( "Budget:" + this.budget ); } } class Memento { private String name; private String phone; private double budget; // Constructors public Memento( String name, String phone, double budget ) { this.name = name; this.phone = phone; this.budget = budget; } public String getName() { return name; } public void setName(String value) { name = value; } public String getPhone() { return phone; } public void setPhone (String value) { phone = value; } public double getBudget() { return budget; } public void setBudget (double value) { budget = value; } } // "Caretaker" class ProspectMemory { private Memento memento; public void setMemento (Memento value){ memento = value; } public Memento getMemento () { return memento; } }
113. Mémento : Exemple(2) public class MementoApp { public static void main(String argv[]) { SalesProspect s = new SalesProspect(); s.setName ( "Landru"); s.setPhone ("08080808"); s.setBudget( 25000.0); s.Afficher(); // Store internal state ProspectMemory m = new ProspectMemory(); m.setMemento( s.SaveMemento()); // Continue changing originator s.setName( "Tintin"); s.setPhone( "33333333"); s.setBudget( 1.0); s.Afficher(); // Restore saved state s.RestoreMemento( m.getMemento() ); s.Afficher(); } }
114. Memento : UML-Dynamique : Client : Caretaker : Originator : Memento <<create>> SaveMemento(): void <<create>> SetState(): void rend le memento SetMemento(p Memento): void GetMemento(): void RestoreMemento(m): void GetState(): void mis a jour de l' é tat()
124. Chain of Resp : Exo Président <100000 Vice-président <25000 Directeur <10000 Comité >=100000 Director grouillot = new Director(); VicePresident Sam = new VicePresident(); President Tammy = new President(); Grouillot.SetSuccessor(Sam); Sam.SetSuccessor(Tammy); Purchase p = new Purchase( 350.00, "Formation"); Grouillot.ProcessRequest(p); p = new Purchase( 24000, "Voiture"); Grouillot.ProcessRequest(p); p =new Purchase ( 99000, "Maison"); Grouillot.ProcessRequest(p); p = new Purchase( 122100.00, "Usine"); Grouillot.ProcessRequest(p); U M V F
129. Command : Correction Architecture Je construis les murs Je construis le toit Je casse le toit Je construis le toit Je casse le toit Je construis le toit Je construis les murs
143. Méthode invoke de non Propriétaire InvocationHandlerNonProprietaire public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if (method.getName().startsWith("get")) { return method.invoke(personne, args); } else if (method.getName().equals("setSexyOuNon")) { return method.invoke(personne, args);} else if (method.getName().startsWith("set")) { throw new IllegalAccessException(); } } catch (InvocationTargetException e) { e.printStackTrace();} return null; }
144. Méthode invoke de Propriétaire InvocationHandlerProprietaire public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if (method.getName().startsWith("get")) { return method.invoke(personne, args); } else if (method.getName().equals("setSexyOuNon")) { throw new IllegalAccessException();} else if (method.getName().startsWith("set")) { return method.invoke(personne, args);} } catch (InvocationTargetException e) {e.printStackTrace();} return null; }
145. Proxy invocationHandler :Exercice(1) le club de rencontres Rmq basedonnees est une Hashtable ---------------------------------------------- Passage difficile :
148. Decorator :Le problème(1) Nous allons revoir la façon dont on abuse généralement de l’héritage et vous allez apprendre comment « décorer » vos classes au moment de l’exécution en utilisant une forme de composition. Pourquoi? Une fois que vous connaîtrez les techniques de décoration, vous pourrez affecter à vos objets (ou à ceux des autres) de nouvelles responsabilités sans modifier le code des classes sous-jacentes. RMQ :Le principe d’Ouverture (n’hésitez pas à étendre nos classes) et de Fermeture (Pas touche à mon code) Un Deca avec du lait et du citron
149. Decorator :Le problème(2) Ecrire les méthodes Boisson::Cout et Colombia::Cout Boisson.Cout() { If GetLait() then cout += coutDuLait If GetVanille() then cout += coutVanille ………………………………………… . Return cout; } Colombia::Cout () { Return 25+ super.Cout() } Que se passe-t-il si on rajoute la crème Chantilly? Il faut modifier Boisson.Cout --- Pas touche à mon code
150. Decorator : UML Decorateuri.Operation(): fait qq chose super.Operation() Cela revient à rajouter une responsabilité à une classe mais sans en changer l'interface. Comparer avec le composite ComposantConcret.Operation : fin de la chaîne Decorateur.Operation() : monComposant.Operation()
151.
152.
153.
154. Decorator : Exemple On utilise l’héritage entre Ingrédient et boisson par Snobisme Boisson::Cout est abstraite Colombia::Cout return 25 (le coût du Colombia sans ingrédient Lait::Cout return le cout du Lait(10) + Le coût de maBoisson Utilisation : Boisson b1 = new Colombia() b1.cout() => 25 Boisson b2 =new Colombia() b2 = new Lait(b2); b2.cout()=> 25 + 10 b2 = new Citron(b2); ….. Colombia Que se passe-t-il si on rajoute la crème Chantilly? Il faut rajouter la classe Chantilly Lait Colombia Citron Lait Colombia
161. L'adaptateur : Exercice Canards oies Canard.Cancaner "Coincoin" Leurre.Cancaner "Silence" CanardPlastique "Pchiff" Oie.Cacarder " CoincoinCoincoin " Pb : Faire cancaner une troupe de Cancaneur contenant des oies
162.
163.
164. Composite : Exercice // Configuration Peripherique p1 = new Peripherique ("DVD", 100,8); Peripherique p2 = new Peripherique ("Disque Dur", 1000,9); Peripherique p3 = new Peripherique ("Modem ADSL", 1,8); Peripherique p4 = new Peripherique ("Pentium", 3500 ,386); Peripherique p5 = new Peripherique ("Ventilo ", 150,15); Container carteMere = new Container ("Carte mère"); carteMere.Ajouter(p4);carteMere.Ajouter(p5); TourDeLuxe tour = new TourDeLuxe ("tour",100); tour.Ajouter(p1);tour.Ajouter(p2);tour.Ajouter(carteMere); Container ordi = new Container ("IBM"); Ordi.Ajouter (tour);ordi.Ajouter (p3); // Utilisation System.out.println( "le prix total est de : " + ordi.GetPrix() ); Composite Leaf le prix d'un ordi Ordi IBM Tour DVD HD Carte mère Modem Adsl Carte mére Pentium Ventilo
171. Flyweight : Poids mouche :UML Utilisation : beaucoup de petits objets à se partager à plusieurs. Exemple : les caractères d'un document PluriGleton
178. Amélioration du singleton L'usine à singleton : Remplacer singletons par singleton Rmq : En C++, mettre en private le constructeur de copie et l'opérateur d'affectation Rmq : En multi thread, utiliser un mutex ou synchronized.
179. Fabrication : Présentation Le problème : If cas1 alors return new c1(); If cas2 alors return new c2(); If cas3 alors return new c3(); Problème de dépendance, ce sous programme dépend de c1,c2,c3…. Et ce problème arrive à chaque fois que l'on veut créer un des ces objets. C'est du code Beurgh! La fabrication va garder et prendre en charge ce code Beurgh, au moins Il sera à un seul endroit. Règle POO : Remplacer le switch par le polymorphisme Fabrication : Garder le switch ce qui évitera de faire des New (et des dépendances)
185. Fabrication exercice les livres Fabrique Le produit FabriquePage fab = new FabriquePage(); Page i = fab.CreatePage("Intro"); i.Afficher(); i=fab.CreatePage("Conclusion"); i.Afficher();
186. Fabrication Abstraite : motivation Application IHM Motif IHM windows Application IHM IHM Motif IHM windows L ’application utilise IHM sans savoir si il s ’agit de Motif ou bien de Windows
197. DP : Exercice général(1) Les stagiaires ont un nom, un sexe et une catégorie (TM, M, Moyen, B , TB). Ils font des exos qui sont réussis en fonction de leur état (TM =4-10, M=5-10, B=10-15, TB=15-20,Moyen =11) Le prof note aléatoirement (presque) les exos mais favorise les filles. (note en fonction de l’état, plus ou moins un nombre compris entre –10 et + 8, rajouter 2 points pour les filles (sauf pour les très bonnes), la note finale est comprise entre 0-20. Quand un élève obtient une note < 7 son état se dégrade, alors que si il obtient une note > 13 son état s’améliore. Le chef vire celui ou celle qui a la plus mauvaise note à chaque exercice. Bill Gates débauche 2 fois le ou la meilleure, tandis que Google n’en débauche qu’un ou qu’une. D’autres personnes, entreprises ou organismes quelconques pourront bientôt s’ intéresser aux stagiaires. Toutes les notes sont sauvegardées pour chaque élève. Abuser Singleton State Observer Strategie Template methode memento
202. RAII : Présentation du pb Tout s’est mal passé et en plus On ne libère pas les ressources out Tout s’est mal passé et en plus On ne libère pas les ressources
204. RAII à la sauce C++ Selon l'approche RAII, on peut modifier la classe Datafile pour qu'elle fasse le Open() dans son constructeur (avec levée d'exception), et le Close() dans son destructeur. Puis l'on crée une petite classe utilitaire DBLock qui gère le verrouillage de la base :
216. Métriques (1) · Lines of Code (LOC) : Le nombre total de lignes de code. Les lignes blanches et les commentaires ne sont pas comptabilisés · Number of Static Methods (NSM) : Le nombre de méthodes statiques dans l'élément sélectionné. · Afferent Coupling (CA) : Le nombre de classes hors d'une package qui dépendent d'une classe dans le package · Normalized Distance (RMD) : RMA + RMI - 1: Ce nombre devrait être petit, proche de zéro pour indiquer une bonne conception des parquets. · Number of Classes (NOC) : Le nombre de classes dans l'élément sélectionné. · Specialization Index (SIX) : NORM * DIT / NOM: Moyenne de l'index de spécialisation. · Instability (RMI) : CE / (CA + CE) : Ce nombre vous donnera l'instabilité de votre projet. C'est-à-dire les dépendances entre les paquets. · Number of Attributes (NOF) : Le nombre de variables dans l'élément sélectionné. · Number of Packages (NOP) : Le nombre de packages dans l'élément sélectionné. · Method Lines of Code (MLOC) : Le nombre total de lignes de codes dans les méthodes. Les lignes blanches et les commentaires ne sont pas comptabilisés · Weighted Methods per Class (WMC) : La somme de la complexité cyclomatique de McCabe pour toutes les méthodes de la classe. · Number of Overridden Methods (NORM) : Le nombre de méthodes redéfinies. · Number of Static Attributes (NSF) : Le nombre de variables statique. · Nested Block Depth (NBD) : La profondeur du code
217. Métriques (2) · Number of Methods (NOM) : Le nombre de méthodes . · Lack of Cohesion of Methods (LCOM) : Une mesure de la cohésion d'une classe. Plus le nombre est petit et plus la classe est cohérente, un nombre proche de un indique que la classe pourrait être découpée en sous-classe. Néanmoins, dans le cas de Javabean, cette métrique n'est pas très correcte, car les getteurs et les settteurs sont utilisés comme seules méthodes d'accès aux attributs. Le résultat est calculé avec la méthode d' Henderson-Sellers : on prend m(A), le nombre de méthodes accédant à un attribut A, on calcule la moyenne de m(A) pour tous les attributs, on soustrait le nombre de méthodes m et on divise par (1-m). · McCabe Cyclomatic Complexity (VG) : La complexité cyclomatique d'une méthode. C'est-à-dire le nombre de chemins possibles à l'intérieur d'une méthode, le nombre de chemin est incrémenté par chaque boucle, condition, opérateur ternaire, # Il ne faut pas que ce nombre soit trop grand pour ne pas compliquer les tests et la compréhensibilité de la méthode. · Number of Parameters (PAR) : Le nombre de paramètres. · Abstractness (RMA) : Le nombre de classes abstraites et d'interfaces divisés par le nombre total de classes dans un package. Cela vous donne donc le pourcentage de classes abstraites par package · Number of Interfaces (NOI) : Le nombre d'interfaces. · Efferent Coupling (CE) : Le nombre de classes dans un packages qui dépendent d'une classe d'un autre package.
218. Métriques (3) · Number of Children (NSC) : Le nombre total de sous-classes directes d'une classe · Depth of Inheritance Tree (DIT) : Distance jusqu'à la classe Object dans la hiérarchie d'héritage. Graphe de dépendances entre packages http://metrics.sourceforge.net/update
219.
220. Table des matières Les patterns Grass 5 Principes fondamentaux de conception 14 Processus objet (up-xp) 32 Processus objet (test-refactoring) 52 ______________________________________ Les design patterns 70 Les design patterns de comportement 75 Automate 76 Stratégie 86 Patron de méthode 90 Observeur 96 Visiteur 105 Memento 110 Iterateur 115 Chaîne de responsabilité 121 Commande 125 Interpréteur 130 Médiateur 131 Les design patterns de structure 132 Proxy 133 Decorateur 147 Adaptateur 158 Composite 162 Façade 167 Poids mouche 171 Pont 173 Les designs patterns de création 175 Singleton 176 Fabrication 179 Fabrication abstraite 186 Builder 190 Prototype 195 _______________________________________ Autres Patterns 200 Les classes d'analyse 201 Raii 202 Patterns et architecture 205 MVC 207