:: Enseignements :: Licence :: L3 :: 2013-2014 :: Programmation Objet avec Java ::
[LOGO]

TP noté 2 - Licence 3


Rappel: vous devez utiliser eclipse-lambda, configurer le JRE pour qu'il pointe sur /usr/local/apps/Java8 et le compilateur pour utiliser la version 1.8. Enfin, vous devez configurer le workspace d'Eclipse (File > Switch WorkSpace) pour qu'il corresponde au répertoire EXAM que vous avez dans le home de votre session de TP noté.
Attention, ce TP est corrigé pour partie de façon automatique! Il est donc très important que le nom des classes et le nom des méthodes que l'on vous demande soit respecté.

Exercice 1 - Y'a pas marqué la poste, là !

On souhaite modéliser le fonctionnement d'un bureau de poste qui permet de délivrer des messages à différents buildings d'une ville.
Le fonctionnement est le suivant: lorsque l'on cherche à envoyer un message (post), on indique un identifiant (identifier) qui correspond au nom du building (au moins dans un premier temps). La poste délivre (deliver) le message à tous les buildings (on verra que l'on peut améliorer l'algorithme plus tard) et chaque building regarde si le message lui est destiné, en comparant l'identifiant avec son nom. Si le nom est le même, le message est stocké dans la boite de réception (mailbox) du building.
L'ensemble des classes à écrire devra être déclaré dans le package fr.umlv.tpnote2.

  1. Écrire une classe CityBuilding qui modélise un building ayant un nom non nul et qui ne change pas.
    En aucun cas, le nom du building ne doit être connu par un code extérieur à la classe.
  2. Écrire une méthode d'affichage telle que le code suivant fonctionne
          CityBuilding building = new CityBuilding("foo");
          System.out.println(building);  // affiche Building foo
        
  3. Écrire une classe PostOffice modélisant un bureau de poste et sa méthode createCityBuilding prenant le nom du building en paramètre.
    Comme un bureau de poste doit connaitre l'ensemble des buildings pour pouvoir distribuer les messages, au lieu de permettre la création d'un building directement, on va changer le code de CityBulding pour obliger quiconque voulant créer un CityBulding à passer par la méthode createCityBuilding de la classe PostOffice.
    Le code suivant ne devra donc plus compiler,
          CityBuilding building = new CityBuilding("foo");
        
    et être remplacé par
          PostOffice postOffice = new PostOffice();
          CityBuilding building = postOfice.createCityBuilding("foo");
        
  4. Écrire la méthode post dans PostOffice qui prend un identifiant et un message (deux chaines de caractères non nulles) et qui délivre le message à l'ensemble des buildings créés aux préalables en appelant createCityBuilding.
    On vous demande pour cela d'écrire une méthode deliver dans la classe CityBuilding. Cette méthode ne doit pas être accessible par une classe hors du package fr.umlv.tpnote2.
    Dans la méthode deliver, si l'identifiant correspond au nom du CityBuilding, on vous demande dans un premier temps d'afficher le message sur la sortie standard (pour tester).
    Écrire de plus un main de test dans la classe Main.
  5. Modifier deliver pour stocker les messages dans une boîte de réception (mailbox). Utiliser pour cela une implantation de l'interface Deque. De plus, pour que les messages soient accessibles depuis n'importe quelle classe, écrivez un getter pour accéder à la mailbox.
    Attention à la signature du getter.
  6. Faire en sorte que si un message n'est pas destiné à un building, celui-ci le signale lors de l'appel à la méthode deliver.
    Dans le cas où tous les buildings refusent le message, post devra afficher que le message n'a pas été délivré.
  7. On souhaite maintenant modéliser des maisons individuelles. Contrairement aux CityBuilding les House sont identifiées par le nom des propriétaires et celui-ci peut changer au cours du temps. De plus, une maison peut aussi être inoccupée.
    Écrire une classe House et une méthode setFamilyName qui permet d'indiquer qu'une famille avec un nom vit dans la maison (il est possible de spécifier un nom nul si personne ne vit dans la maison). Écrire également sa méthode d'affichage de telle sorte que le code suivant fonctionne.
          House house = new House();
          house.setFamily("McDonald");
          System.out.println(house);   // McDonald's house
          house.setFamily(null);       
          System.out.println(house);   // empty house
        
  8. On souhaite maintenant que les House puissent aussi recevoir du courrier. Pour cela, créer une méthode createHouse sans paramètre dans PostOffice.
    Modifier le code de post pour que l'on puisse envoyer des messages aussi bien aux CityBuilding qu'aux maisons. Le code suivant devra donc fonctionner.
          PostOffice postOffice = new PostOffice();
          House house = postOfice.createHouse();
          house.setFamily("McDonald");
          postOffice.post("McDonald", "hello Mc");
          System.out.println(house.getMailbox());  // [hello Mc]
          house.setFamily("null");
          postOffice.post("McDonald", "hello Mc"); // message not delivered !
        

    Attention, vous devez implanter post de façon objet !
  9. Modifier votre implantation pour que, si l'on post un message avec l'identifiant citybroadcast, celui-ci soit délivré dans toutes les mailbox des CityBuilding.
  10. On veut améliorer l'algorithme de distribution des messages mais toujours sans que le bureau de poste sache si un building ou une maison va répondre à un message. L'idée est la suivante, si deliver répond qu'un message est a été délivré alors on enregistre dans un cache que le building (ou la maison) est capable de comprendre l'identifiant et au prochain post, au lieu d'envoyer le message à toutes les buildings (et maisons), on essaiera d'envoyer le message en premier à ce building. Dans le cas où le building (ou la maison) répondrait par la négative (par exemple si la famille a déménagé pour une maison, il faudra invalider l'entrée dans le cache.
    Implanter l'algorithme décrit ci-dessus en sachant qu'une HashMap fait un très bon cache et qu'il faut faire attention aux messages de broadcast.
  11. Lorsque une nouvelle famille arrive dans une maison, (avec setFamily), s'il y a des messages dans la mailbox, ceux-ci doivent être renvoyés automatiquement au bureau de post pour être re-postés vers la nouvelle maison occupée par cette famille.
          PostOffice postOffice = new PostOffice();
          House house = postOfice.createHouse();
          house.setFamily("McDonald");
          postOffice.post("McDonald", "hello Mc");
          House newHouse = postOfice.createHouse();
          newHouse.setFamily("McDonald");
          house.setFamily(null);  // les MacDonald ont déménagé
          System.out.println(newHouse.getMailbox());  // [hello Mc]
        
  12. On souhaite rendre le système un peu plus flexible. L'idée est qu'au lieu d'envoyer des messages sous forme de chaines de caractères, on va pouvoir envoyer des commandes (Command) qui seront exécutées par les buildings (et/ou maisons) ayant reçu ces commandes (donc pas de stockage dans la mailbox dans ce cas).
    Une commande est une fonction qui prend en paramètre le building (ou la maison) ayant reçu la commande.
    Le code suivant devra alors fonctionner
          PostOffice postOffice = new PostOffice();
          CityBuilding kino = postOfice.createCityBuilding("kino");
          postOffice.postCommand("kino", building -> System.out.println("hello from " + building));  // hello from kino
        
    De plus, la méthode post devra être ré-écrite pour utiliser postCommand.