TD n°4 : Le Pattern Singleton
Voici un exercice simple : des avions sont créés par le programme principal. L'aéroport possède une tour de contrôle, qui gère l'unique piste. Quand un avion souhaite décoller ou atterrir, il attend que la tour de contrôle l'autorise. Deux avions ne doivent pas réserver la piste simultanément, sous peine d'accident.
La classe LoadAndShow ne nécessite pas d'attention.
1. Analyse du comportement initial
Si vous exécutez le programme principal, quel résultat obtenez-vous ? Que fait la méthode start lorsqu'elle est appelée sur un objet Plane ? Pouvez-vous identifier le problème ? Proposez des solutions pour corriger ce dysfonctionnement sans modifier les classes Airport, Plane et Main.
2. Implémentation de la solution
Après avoir discuté avec l'intervenant du TP, implémentez la solution retenue. Votre programme fonctionne-t-il correctement ?
3. Validation du code
Téléchargez les nouvelles classes (remplacez le Main existant) et testez votre code.
4. Test avec un délai d'exécution
Dans la classe ControlTower, ajoutez un appel à Thread.sleep(1) avant toute création d'objet via new. Votre code fonctionne-t-il toujours ? Si oui, augmentez la durée du Thread.sleep. Pourquoi le code ne fonctionne-t-il plus après un certain temps ? Proposez des améliorations pour le rendre fonctionnel.
5. Correction de la solution
Implémentez les modifications nécessaires après discussion avec l'intervenant. Tout fonctionne-t-il ?
6. Transformation de la classe Airport
Modifiez la classe Airport pour que ses méthodes ne soient plus statiques et appliquez également le pattern Singleton. Adaptez en conséquence la classe ControlTower. Votre programme fonctionne-t-il toujours ?
Le Pattern Décorateur : René la Taupe
Votre travail à la tour de contrôle de Brétigny-sur-Orge a été récompensé par une promotion : vous êtes désormais intégré au club Jamba dans le département des applications mobiles.
1. Ajout d'un chapeau à René
Récupérez le code fourni et activez la partie permettant de placer un chapeau sur René.
2. Ajout de lunettes de soleil
Les lunettes de soleil doivent être positionnées aux coordonnées (255, 76). Écrivez le code pour les afficher sur René.
3. Génération de logos variés
Récupérez d'autres éléments : le bâton de sucrerie (position : 441, 202), la chanson (position : 10, 10), et le smiley (position : 260, 210). Écrivez un code pour générer facilement des logos de René avec lunettes, chapeau, etc. Créez une interface commune pour tous les accessoires que René peut porter, permettant aux autres équipes de générer ces logos en une seule ligne de code.
4. Combinaison d'accessoires
Modifiez votre code pour combiner facilement ces éléments. L'objectif est de proposer une génération simple d'un nouveau logo en une seule ligne de code. Regroupez tous les éléments (accessoires et René) sous une interface commune appelée SuperLogo. Ensuite, créez une classe abstraite Accessoires pour regrouper les accessoires, et ajoutez un élément de type SuperLogo dans Accessoires. Déclenchez des réactions en chaîne entre les SuperLogos pour superposer facilement tous les éléments.
5. Calcul du prix des logos
Implémentez une méthode prix permettant de calculer le coût total d'un ensemble de logos, en utilisant des réactions en chaîne. Chaque accessoire a un prix, qui s'ajoute à celui de René.
6. Ajout d'une moustache
En raison de la grève, une moustache comme celle de José Bové est demandée. Ajoutez cet accessoire à votre code.
7. Intégration de Crazy Frog
En Creuse, une nouvelle tendance « Crazy Frog » émerge. Le club Jamba souhaite proposer des logos basés sur cette image. Ajoutez facilement une nouvelle image de base « Crazy Frog » à votre code.
Le Pattern State : Distributeur Automatique de Billets
Vous avez été embauché par la mairie de Guéret pour développer un distributeur automatique de billets moderne.
1. Implémentation de base
Le distributeur possède trois états : pas de carte insérée, en attente d'opération, et en attente de retrait d'espèces. Quatre actions sont possibles : insérer une carte, entrer un code, retirer des espèces, retirer la carte. Selon l'état, ces actions ont des conséquences différentes.
Voici un extrait de code pour la machine :
public class Distributeur {
final static int etat_pas_de_carte = 0;
final static int etat_attente_code = 1;
final static int etat_attente_operation = 2;
private int etat;
private Carte c;
public Distributeur() { etat = etat_pas_de_carte; }
public void inserer_carte(Carte client) {
if (etat == etat_pas_de_carte) {
System.out.println("Insertion carte Client");
c = client;
} else if (etat == etat_attente_code) {
// ...
}
// ...
}
}
La classe Carte contient un constructeur prenant un code secret et une méthode vérifiant si le code entré est correct.
Si le client entre trois fois un mauvais code, la carte est avalée. Implémentez le distributeur.
2. Refactorisation avec l'interface État
Créez une interface ou une classe abstraite Etat contenant les quatre méthodes du distributeur (insérer carte, entrer code, retirer argent, reprendre carte). Implémentez trois classes Etat, chacune représentant un état possible de la machine.
Le distributeur doit posséder trois variables de classe (une par état possible) et une variable de classe de type Etat pour son état courant. À chaque appel d'une méthode, il doit déléguer l'exécution à son état courant. Ajoutez une méthode pour modifier l'état courant.
3. Ajout de l'état MachineVide
Implémentez un nouvel état MachineVide pour empêcher le retrait d'argent lorsque la machine est vide. Ajoutez une variable de classe pour gérer le stock d'argent et vérifiez son solde avant de distribuer des espèces. Était-ce complexe ?
4. Lecture du solde du compte
Ajoutez une méthode lire_solde_compte pour permettre au client d'accéder à son solde lorsque le distributeur est en mode « En Attente Pour Retirer Argent ». Était-ce difficile ?
FAQ
1. Qu'est-ce que le Pattern Singleton ?
Le Pattern Singleton garantit qu'une classe ne peut avoir qu'une seule instance et fournit un point d'accès global à celle-ci. Il est utile pour gérer des ressources uniques comme une tour de contrôle ou un distributeur de billets.
2. Comment le Pattern Décorateur simplifie-t-il la création de logos variés ?
Le Pattern Décorateur permet d'ajouter dynamiquement des responsabilités à un objet sans modifier sa structure. Ainsi, chaque accessoire (lunettes, chapeau, etc.) peut être superposé facilement à l'image de base.
3. Pourquoi utiliser le Pattern State pour un distributeur automatique ?
Le Pattern State est idéal pour les machines d'état, car il isole chaque état dans une classe distincte. Cela facilite l'ajout de nouveaux états (comme MachineVide) et rend le code plus maintenable et extensible.