Design patterns Conception UML Implantation Java Anne Lapujade 1 Design patterns - définition 2 v Objectif : proposer des solutions standardisées à des problèmes de conception classiques v Design pattern Patron/Masque de conception n Solution abstraite réutilisable indépendante d un langage de programmation n Exprimé sous forme d architecture reliant quelques classes très abstraites n Raisons de l utilisation ou pas du pattern n Conséquences liées à l utilisation du pattern n Suggestions pour implanter la solution. Design patterns - avantages 3 v Vocabulaire commun v Capitalisation de l expérience v Niveau d abstraction plus élevé => meilleures constructions logicielles v Réduction de la complexité v Catalogue de solutions 1
Design patterns - inconvénients 4 v Effort de synthèse : abstraire, reconnaître v Apprentissage, expérience v Les patterns se dissolvent en étant utilisés v Multiplication des patterns, patterns imbriqués, de niveaux différents Design patterns - GOF 5 v Gamma, Helm, Johnson, Vlissides «Design patterns : elements of reusable object-oriented software» n Édité en 1996 n 23 patterns qui sont la référence v Trois types de patterns n Créateurs n Structuraux n Comportementaux Design pattern createur 6 v Abstraire le processus d instanciation v Rendre indépendant la façon dont les objets sont créés, composés, assemblés, représentés v Encapsuler la connaissance de la classe concrète qui instancie v Cacher ce qui est créé, qui crée, comment et quand 2
Singleton 7 v Créateur v Gestion d une classe à instance unique Singleton 8 v Modèle conceptuel Singleton -instance : Singleton +getinstance() : Singleton Singleton 9 v Exemples n Gestion du son, de textures n Gestion d une connexion entre un client et un serveur unique n Gestion du temps dans un jeu n Pool de connexion à une BD n Printer spooler, file system, windows manager 3
Singleton 10 v Implantation package singleton; public class Singleton { private static Singleton instance; private int i; public static synchronized Singleton getinstance(){ if (instance == null) instance = new Singleton(); return instance; public void setvalue(int value) { i = value; public int getvalue() { return i; private Singleton() { Singleton 11 v Implantation public class SingletonClient { public static void main(string[] args) { Singleton s = Singleton.getInstance(); System.out.println("La valeur de i est " + s.getvalue()); Singleton s2 = Singleton.getInstance(); System.out.println("La valeur de i est " + s2.getvalue()); // Changement de la valeur du Singleton s.setvalue(20); System.out.println("La valeur de i est " + s.getvalue()); System.out.println("La valeur de i est " + s2.getvalue()); Prototype 12 v Créateur v Gestion du clonage des objets n Permet de faire des copies d objets sans en connaître le type v Exemples n Gestion des monstres dans un jeu vidéo n Simulation de la division cellulaire 4
Prototype 13 v Modèle conceptuel Client +getprototype() * * PrototypeAbstrait -att1 : int +clone() : Object +getatt1() : int +setatt1(entrée natt1 : int) PrototypeConcret1 -att2 : int +getatt2() : int +setatt2(entrée natt1 : int) PrototypeConcret2 -att3 : int +getatt3() : int +setatt3(entrée natt1 : int) SousPrototypeConcret1 -att4 : int +getatt4() : int +setatt4(entrée natt1 : int) Prototype 14 v Code classe abstraite public abstract class PrototypeAbstrait implements Cloneable { int att1; public void setatt1(int natt1) { this.att1 = natt1; public int getatt1() { return this.att1; @Override protected Object clone() throws CloneNotSupportedException { Object object = null; object = super.clone(); // Le clonage copie les attributs membres à membres de l'original vers le clone // ATTENTION AUX ALIAS // Rajouter du code ici pour gérer le pb des alias return object; Prototype 15 v Code classes à cloner public class PrototypeConcret1 extends PrototypeAbstrait { protected int att2=5; public int getatt2() { return att2; public void setatt2(int natt2) { this.att2 = natt2; public PrototypeConcret1() { setatt1(1); 5
Prototype v Client 16 PrototypeConcret pc1=new PrototypeConcret(); // Clonage PrototypeConcret pc2 = (PrototypeConcret) pc1.clone(); Builder 17 v Créateur v Classe offrant des moyens de construction d un objet Builder 18 v Modèle conceptuel 6
Builder v Exemple n La préparation de pizzas 19 Builder v Code source : le director 20 public class Cook { private PizzaBuilder pizzabuilder; public void setpizzabuilder(pizzabuilder pb) { pizzabuilder = pb; public Pizza getpizza() { return pizzabuilder.getpizza(); public void cookpizza() { pizzabuilder.createnewpizzaproduct(); pizzabuilder.builddough(); pizzabuilder.buildsauce(); pizzabuilder.buildtopping(); Builder v Code source : les constructeurs public abstract class PizzaBuilder { protected Pizza pizza; public Pizza getpizza() { return pizza; public void createnewpizzaproduct() { pizza = new Pizza(); public abstract void builddough(); public abstract void buildsauce(); public abstract void buildtopping(); 21 public class SpicyPizzaBuilder extends PizzaBuilder { public void builddough() { pizza.setdough("pan baked"); public void buildsauce() { pizza.setsauce("hot"); public void buildtopping() { pizza.settopping("pepperoni+salami"); 7
Builder 22 v Code source : le produit public class Pizza { private String dough = ""; private String sauce = ""; private String topping = ""; public void setdough(string dough) { this.dough = dough; public void setsauce(string sauce) { this.sauce = sauce; public void settopping(string topping) { this.topping = topping; Builder 23 v Code source : l utilisation Cook cook = new Cook(); PizzaBuilder hawaiianpizzabuilder = new HawaiianPizzaBuilder(); PizzaBuilder spicypizzabuilder = new SpicyPizzaBuilder(); cook.setpizzabuilder(hawaiianpizzabuilder); cook.constructpizza(); Pizza pizza = cook.getpizza(); Design patterns structuraux 24 v Comment les objets sont assemblés v Les patterns sont complémentaires les uns des autres 8
Composite 25 v Structurel v Composition d objets dans des structures de type arbre Composite 26 v Modèle conceptuel Client Noeud +operation() +add() +remove() +getchild() * NoeudTerminal NoeudNonTerminal +add() +remove() +getchild() 1 Composite 27 v Exemple n JPanel n Menus dans une application n Système de fichiers 9
Composite 28 v Exemple le système de fichiers SGF ElementStockage * 1 * Fichier Repertoire 1 Composite v Code source ElementStockage 29 public abstract class ElementStockage { protected String nome; public ElementStockage(){ nome=""; public ElementStockage(String nom){ nome=nom; public String getnom() { return nome; public void setnomfic(string nomel) { this.nome = nomel; public abstract boolean add(elementstockage e); public abstract boolean remove(elementstockage e); public boolean display(int indentation){ for (int i=0; i<indentation; i++){ System.out.print("\t"); System.out.println(nome); return true; Composite 30 v Code source public class Fichier extends ElementStockage { public Fichier(String nom){ super(nom); public boolean add(elementstockage e){ System.out.println("Impossible de rajouter"); return false; public boolean remove(elementstockage e){ System.out.println("Impossible de supprimer"); return false; public class Repertoire extends ElementStockage{ private ArrayList elements; public Repertoire(String nom){ super(nom); elements=new ArrayList(); public boolean add(elementstockage e){ elements.add(e); return true; public boolean remove(elementstockage e) { elements.remove(e); return true; public boolean display(int indentation) { super.display(indentation); for (int i=0; i<elements.size();i++) { ((ElementStockage)elements.get(i)).display(indentation+1); return true; 10
Composite 31 v Code source public class Utilisation { public static void main(string[] args) { Repertoire root=new Repertoire ("Racine"); Repertoire win=new Repertoire("Windows"); Repertoire md=new Repertoire("Mes Documents"); Repertoire win32=new Repertoire("win32"); win.add(win32); root.add(win); root.add(md); root.add(new Fichier("autoexec.bat")); win.add(new Fichier("win.ini")); md.add(new Fichier("projet.doc")); win32.add(new Fichier("calc.exe")); root.display(0); Decorator 32 v Structurel v Ajout dynamique de responsabilités à un objet Decorator 33 v Cas d utilisation n Ajouter des attributs à des objets de façon dynamique et transparente n Pour avoir des attributs optionnels n Quand l héritage n est pas adapté Création de nombreuses sous classes 11
Decorator v Avantages n Plus flexible que de l héritage statique n Evite des classes chargées d attributs en haut de la hiérarchie v Inconvénients n Beaucoup de petits objets n Un décorateur et ses composants ne sont pas identiques : attention à la vérification de l identification des objets 34 Decorator 35 v Modèle conceptuel Implémentation Composant Decorateur On construit à la chaîne le composant en créant un nouveau composant qui utilise l ancien avec une décoration supplémentaire Decoration1 Décoration2 Decorator 36 v Exemple Sans décorateur Avec décorateur ElementInterface ZoneTexte 1 -AscVertical 1 1 ZoneTexte DecorateurVisuel 0..1 -AscHorizontal 0..1 0..1 Bordure Ascenseur Bordure Ascenseur Bordure3D BordureSimple AscHorizontal AscVertical Bordure3D BordureSimple AscHorizontal AscVertical 12
Decorator v Exemple gestion des logs n Logs sous différentes formes w Affichage console w Affichage swing w Fichier w email n Gérer l ajout de deux attributs optionnels : date et heure d ajout d un message dans le log n Solution non retenue = surcharger la classe log pour chaque utilisation => prolifération de classes 37 Decorator v Exemple Les logs n On dispose d un logger permettant d afficher un message dans la console ou dans un Stream n On veut rajouter w Ajouter la date pour chaque message w Afficher les messages dans un JTextArea 38 Decorator v Exemple 39 «interface»logger DefaultLogger DecoratorLogger LoggerWithDate LoggerSwing 13
Decorator v Code source la classe à décorer 40 public class DefaultLogger implements Logger { private PrintStream stream; public DefaultLogger() { public DefaultLogger(PrintStream stream) { this.stream = stream; public void setstream(printstream stream) { this.stream = stream; public PrintStream getstream() { return (this.stream!= null)? this.stream : System.out; public String log(string msg) { this.getstream().println(msg); return msg; Decorator 41 v Code source Composant et décorateur public interface Logger { public String log(string msg); public abstract class DecoratorLogger implements Logger { protected Logger logger; public DecoratorLogger(Logger logger) { this.logger = logger; public String log(string msg) { return logger.log(msg); public Logger getlogger() { return this.logger; public void setlogger(logger logger) { this.logger = logger; Decorator 42 v Code sources Les décorations public class LoggerWithDate extends DecoratorLogger { public LoggerWithDate(Logger logger) { super(logger); public String log(string msg) { return "Date : " + LoggerWithDate.getDate(new Date()) + " - " + super.log(msg); public static String getdate(java.util.date date) { SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); return formatter.format(date); public class LoggerSwing extends DecoratorLogger { protected JTextArea txtfieldlog; public LoggerSwing(Logger logger, JTextArea txtfieldlog) { super(logger); this.txtfieldlog = txtfieldlog; public String log(string msg) { txtfieldlog.settext(txtfieldlog.gettext() + "\n" + super.log(msg)); return msg; 14
Decorator v Code source les clients class FrameLog extends JFrame { protected JTextArea txtconsolelog; public FrameLog(String title){ this.settitle("logger : " + title); this.setsize(300, 300); txtconsolelog = new JTextArea(); this.getcontentpane().add(txtconsolelog); this.setdefaultcloseoperation(jframe.dispose_on_close); public JTextArea getfieldlog() { return this.txtconsolelog; public class Client { public static void main(string[] args) { FrameLog framelog = new FrameLog("TestLogger"); framelog.show(); Logger logger = new DefaultLogger(); // Ajoute une fonctionnalité (date) LoggerWithDate loggerwithdate = new LoggerWithDate(logger); // Ajoute la fonctionnalité : Swing LoggerSwing loggerswing = new LoggerSwing(loggerWithDate, framelog.getfieldlog()); // Affiche un log logger.log("test1"); // Affiche le log dans le Swing loggerswing.log("test2"); // Affiche le log dans le swing (sans date) loggerswing.setlogger(logger); loggerswing.log("fin"); 43 Design patterns comportementaux v Description n D algorithmes n De comportements entre objets n De formes de communication entre objets 44 Observer v Comportemental v Définition de dépendances entre objets v Lorsque le sujet change d'état, les observateurs en sont avertis automatiquement 45 15
Observer 46 v Cas d'utilisation n Un objet dispose de plusieurs "listeners" n Le changement d'un objet se répercute vers d'autres n Un objet doit prévenir d'autres objets sans les connaître Observer v Modèle conceptuel 47 Observer 48 v Deux règles n Le sujet ne sait rien de l'observateur n L'observateur ne modifie jamais le sujet è Séparation sujet/observateur 16
Observer 49 v Exemples n Un histogramme et un camembert qui bougent lorsqu'on change les valeurs d'une colonne dans Excel n Eclipse/jigloo : le plugin positionne sur le code source lorsque l'on clique sur un élément graphique n Forum de discussions : ex mailing automatique des modérateurs lors d'un nouveau message Observer 50 v Exemple : la boutique en ligne v Une boutique souhaite offrir un cadeau à chacun de ses clients par tranche de 10 produits commandés dans un même pannier Observer 51 v Exemple : la boutique en ligne 17
Observer 52 v La boutique code source l'observé public class Pannier extends Observable{ private int nbpdtscdes; private ArrayList lignescommande; private ArrayList cadeaux; private String leclient; public Pannier(String c) { nbpdtscdes=0; lignescommande=new ArrayList(); cadeaux=new ArrayList(); leclient=c; public void ajouterarticle(string ref, int qte) { // l'ajout de la ligne de cde nbpdtscdes++; setchanged(); notifyobservers(); // Appelle Update de la Boutique public int getnbproduitscdes() {return nbpdtscdes; public String getclient(){return leclient; public void addcadeau(string c){ cadeaux.add(c); Observer 53 v Exemple la boutique l'observeur public class Boutique implements Observer{ private Pannier pannier; private ArrayList cadeaux; public Boutique() { pannier=null; cadeaux = new ArrayList(); String c1="cadeau1"; cadeaux.add(c1); String c2="cadeau2";cadeaux.add(c1); String c3="cadeau3";cadeaux.add(c1); public void ajouterpannier(pannier p) { p.addobserver(this); public void update(observable o, Object arg) { pannier=(pannier)o; System.out.println("update du sujet "+pannier.getclient()); if (pannier.getnbproduitscdes()%3==0) { pannier.addcadeau((string)cadeaux.get(pannier.getnbproduitscdes()/10)); Observer 54 v Exemple la boutique - utilisation public class Utilisation { public static void main(string[] args) { Boutique b=new Boutique(); Pannier p1=new Pannier("Dupont"); Pannier p2=new Pannier("Durant"); p1.addobserver(b); p2.addobserver(b); p1.ajouterarticle("cle de 12",3); p2.ajouterarticle("ampoule 100W",1); p1.ajouterarticle("tournevis",1); p1.ajouterarticle("boulons",100); 18
Iterator 55 v Comportemantal v Permet d'accéder à tous les éléments d'un agrégat séquentiellement sans exposer sa stucture interne Iterator 56 v Cas d'utilisation n Besoin d'accéder à une liste d'éléments suivant un moyen précis w Croissant w Décroissant w Insertion n Besoin d'appliquer une filtre particulier à une liste (sélectionner les éléments qui commencent par 'a'...) Iterator 57 v Modèle conceptuel 19
Iterator 58 v Avantages n Fournit plusieurs moyens de parcourir unr relation tout-partie n Simplifie l'ajout de parties dans une relation tout-partie n Simplifie la navigation dans des hiéracrchies tout-partie n Simple d'utilisation en permettant au client de traiter de manière générique le tout ou ses parties Iterator 59 v Exemple : le framework Collection en Java Iterator 60 v Exemple LinkedList List list=new LinkedList(); list.add(new String("mot1")); list.add(new String("mot2")); list.add(new String("mot3")); ListIterator iterator=list.listiterator(); while (iterator.hasnext()){ String contenu=(string)iterator.next(); System.out.println(contenu); if (contenu.compareto("mot2")==0) { iterator.remove(); iterator.add(new String("mot4")); while (iterator.hasprevious()){ String contenu=(string)iterator.previous(); System.out.println(contenu); 20