Cours BUT Info

TP 1 — Patrons de conception

Crêpes et gaufres : Décorateur, Composite, Fabrique simple, ObjetNull et Stratégie — l'énoncé, puis un corrigé pas à pas avec le code complet de chaque étape.

Objectifs et mise en place

  • comprendre ce qu'est un patron et ce que ça veut dire de l'employer ;
  • comprendre et retenir le principe des patrons Décorateur, Composite, Fabrique, ObjetNull et Stratégie utilisés dans ce TP.

Mise en place

Créez un projet Java tp1-patrons-conception dans un répertoire dédié à l'ensemble de vos TP (par ex. r304). Choisissez Maven comme build system, et cochez la création d'un dépôt git local : des commits réguliers au fil des exercices, c'est une bonne habitude. Le cours sur les patrons contient une présentation des patrons utilisés ici — n'hésitez pas à le consulter.

Le fil rouge du TP : vendre des crêpes et gaufres sur lesquelles on rajoute des garnitures. Deux opérations sur un dessert : récupérer son prix et son nom.

NomPrix
DessertsCrêpe3 €
Gaufre3,50 €
GarnituresChantilly1 €
Chocolat1,50 €
Coulis de fraise2 €

Chaque partie du sujet se travaille en deux temps : d'abord un temps de réflexion (avec de l'UML), puis un temps d'implémentation — et vous serez de moins en moins guidés. Essayez par vous-même avant d'ouvrir les corrigés : c'est en butant qu'on retient.

1. Décorateur : le double supplément chantilly-chocolat

Une garniture est un dessert qui contient un dessert : le dessert joue le rôle de Component, la Garniture celui de Decorator. Cette conception permet plusieurs garnitures sur un même dessert, empêche de prendre une garniture seule ou de garnir une crêpe par une gaufre :

Dessert d = new Chocolat(new Chantilly(new Gaufre()));
System.out.println(d);   // Gaufre chantilly chocolat – 6€

Vérifier avant d'avancer

Un fichier de test est fourni sur Moodle : intégrez-le dans src/test/java/patisserie/garniture en adaptant noms et imports. Les tests se vérifient automatiquement après chaque modification — lancez-les régulièrement, notamment avant chaque commit. Complétez aussi l'UML distribué avec le patron Décorateur tel qu'appliqué, et faites valider par votre enseignant·e.

Une fois le patron Décorateur en place, le reste du TP se travaille en deux temps : d'abord un temps de réflexion (avec de l'UML), puis un temps d'implémentation.

L'UML du TP une fois complété : Dessert est le Component, Garniture le Decorator, Assortiment le Composite, DessertNull l'objet nul, et la FabriqueDessert externalise la construction. L'exemple du sujet : new Chocolat(new Chantilly(new Gaufre())) vaut « Gaufre chantilly chocolat – 6 € ».

2. Composite : et un café gourmand !

On veut des assortiments de desserts pour les commandes de groupe : un assortiment est un dessert composé de plusieurs desserts. Son prix est la somme des prix avec un rabais de 10 % ; son nom est celui de l'assortiment suivi, entre parenthèses, de tout ce qu'il contient :

Assortiment
- Crêpe
- Gaufre chantilly chocolat
8.1 €

À vous de dire, dans le patron Composite : à quoi correspond l'assortiment ? Le dessert ? La crêpe ? Bonne nouvelle annoncée par le sujet : des ajouts, a priori aucune modification des classes existantes. Les assortiments doivent pouvoir contenir eux-mêmes des assortiments — dont les desserts peuvent être garnis.

3. Fabrique simple : passez commande

Instancier les desserts à la main est fastidieux. On externalise la construction des objets d'un même super-type dans une classe dédiée : la Fabrique simple. Objectif : créer un dessert à partir d'un texte, par exemple Gaufre chantilly chocolat (sans les assortiments pour l'instant). Pour décomposer la commande, un simple split() et l'analyse du tableau résultant suffisent. La chaîne Gaufre chantilly chocolat doit produire un objet équivalent à :

new Chocolat(new Chantilly(new Gaufre()));

4. Objet null : évitons de nous gaufrer

Une erreur de saisie (absence d'un dessert de base, garniture inconnue) peut faire planter le programme. En cas d'erreur, la fabrique retourne un objet « dessert null » — et non la valeur nulle. Mettez à jour l'UML, implémentez, vérifiez.

5. Stratégie : passez à la caisse !

Différents niveaux de détail sur le ticket, selon qu'il s'agit d'un cadeau ou non et selon la largeur du rouleau :

  • l'interface TicketDessert avec une seule méthode : String getTicket(Dessert dessert) ;
  • trois implémentations :
    1. le nom et le prix du dessert ;
    2. uniquement le nom (pour les cadeaux) ;
    3. les informations condensées sur un nombre de caractères limité, passé en paramètre à la construction ;
  • une classe Borne qui lit les commandes et affiche le ticket correspondant, avec un scénario : l'utilisateur saisit une commande, choisit le mode d'édition du ticket, le ticket s'affiche.

6. La cerise sur le gâteau

  • le rabais d'un assortiment à plusieurs niveaux ne doit être effectué qu'une seule fois ;
  • s'il est possible d'ajouter une garniture sur un assortiment, revoyez la conception pour l'empêcher ;
  • la fabrique doit aussi gérer les assortiments (une commande contenant plusieurs desserts est un assortiment) ;
  • adaptez modèle et fabrique pour gérer aussi les bons de réduction ;
  • et n'oubliez pas les tests !

tp1-patrons-de-conception.pdf

R3.04 · TP 1 — Fabien Delecroix · 7 pages

Consultation seule — téléchargement désactivé

Chargement du document…

Dernière mise à jour le

Sur cette page