:: Enseignements :: ESIPE :: E4INFO :: 2018-2019 :: Programmation Orientée Objet - Design Patterns ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Je loggue, tu loggues, ... |
Decorateur externe, Decorateur interne, Proxy et Composite
Exercice 1 - Mon logger à moi
Votre entreprise, elle aussi atteinte du
syndrome NIH, utilise la classe suivante
Bien sûr, elle ne permet de logguer des messages que sur la sortie d'erreur standard mais nous allons améliorer cela.
-
Pour exemple, que pensez-vous du schéma page 3 de log4j ?
-
On souhaite aussi pouvoir compter le nombre de chaque niveau d'erreurs envoyées au logger,
on se propose donc d'écrire une nouvelle classe pour logguer : CounterLogger avec une méthode supplémentaire
int getLevelCounter(Level level) qui renvoie un entier indiquant le nombre d'erreurs
reçues pour le niveau d'erreur spécifié.
Ecrire la classe CounterLogger.
Note de Java: Il existe une classe java.util.EnumMap qui possède deux méthodes intéressantes
getOrDefault() et merge !
-
En tant que développeur, on souhaite pouvoir manipuler indifféremment un SystemLogger ou
un CounterLogger à travers la même API.
Faite les changements qui s'impose.
-
On peut remarquer que créer plusieurs instances de SystemLogger est un peu idiot,
on pourrait partager la même instance.
Quel design pattern doit-on utiliser dans ce cas ?
Faites les changements qui s'impose dans la classe SystemLogger.
-
-
On souhaite pouvoir filtrer les logs du CounterLogger, c-a-d afficher les logs qui sont plus grands ou plus petits
qu'un certain Level.
Comment doit-on faire ?
Implanter la solution retenue.
PS: pour plus de flexibilité on representera le fait de choisir si on affiche un Level
ou non par un Predicate<Level> pour ne pas hardcoder le choix d'un Level
dans le code.
attention : pourquoi ne faut-il pas modifier votre interface Logger ?
-
On veut aussi permettre de filtrer les logs sur le SystemLogger et plus généralement
sur n'importe quel logger.
Expliquer pourquoi utiliser une classe abstraite qui contient un Predicate
pour partager le code ne marche pas ici ?
-
Comment le design pattern Proxy
permet de résoudre le problème ?
Modifier votre code pour implanter ce design pattern.
-
En fait, dans 90% des cas, on ne rend pas la classe du proxy publique.
Expliquer pourquoi et comment un utilisateur va utiliser la classe ?
Faire les changements qui s'imposent dans le code.
-
Votre chef a essayé de créer un nouveau Logger, un PathLogger
avec le code suivant:
public class PathLogger implements Logger {
private final BufferedWriter writer;
public PathLogger(Path path) throws IOException {
this.writer = Files.newBufferedWriter(path,
StandardOpenOption.APPEND);
}
@Override
public void log(Level level, String message) {
try {
writer.write(level.name() + ' ' + message);
writer.newLine();
writer.flush();
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}
}
mais il veut le tester comme ceci:
public class Foo {
...
private static final PathLogger logger = new PathLogger(Paths.get("log.txt"));
}
le code ne compile pas car il manque la gestion des exceptions d'entrée/sortie.
(la classe PathLogger à aussi un problème car il n'y a pas de close
mais ce n'est pas ce qui nous intéresse ici).
Au lieu de devoir gérer les exceptions dans un bloc statique, il vous demande d'écrire
du code qui essaye de creér un PathLogger et s'il n'y arrive pas pour cause
d'exceptions, renvoie un SystemLogger à la place.
Bien sûr ce code devra pouvoir être appelé avec des fichiers de log différents.
Quel design pattern doit on mettre en oeuvre ici ?
Ecrire le code correspondant.
-
Enfin, on souhaite pouvoir créer des loggeurs capable par exemple d'afficher ses logs
sur la console et de maintenir les compteurs pour chaque level d'erreur.
Comment doit-on implanter un tel logger ? faites le schéma UML.
Ecrire le code correspondant.
Assurez-vous que votre solution permet d'avoir un filtrage différent sur le compteur de logs et la console.
-
faites le schéma UML récapitulatif de ce TD.
© Université de Marne-la-Vallée