:: Enseignements :: ESIPE :: E4INFO :: 2018-2019 :: Programmation Orientée Objet - Design Patterns ::
[LOGO]

ça vaut le détour


Ce TD se déroule en autonomie. Les rendus sont à faire sur la plate-forme elearning. Les consignes précises du rendu : Rappel : le travail en autonomie peut inclure des discussions entre vous mais le résultat / le rendu doit être le résultat de VOTRE compréhension.

Exercice 1 - Questions

Les réponses aux questions doivent être faites en 15 minutes maximum Ne faites pas de copier/coller Wikipedia ! ce qui nous intéresse, c'est votre compréhension et vos mots !

  1. Selon vous, quel est l'avantage principal du design pattern Visitor
  2. Selon vous, quel est l'inconvénient principal du design pattern Visitor
  3. Parcourez la javadoc sur ElementVisitor. Exprimez brièvement votre compréhension.

Exercice 2 - Encore une calculette !

Le but de cet exercice est modifier un code existant permettant d'effectuer le calcul d'une expression en polonaise inverse dans le but de fermer la hiérarchie d'expression tout en laissant la possibilité à un utilisateur d'écrire ses propres traitements.

Le code suivant permet d'évaluer une expression en polonaise inverse
     Iterator<String> it = Pattern.compile(" ").splitAsStream("+ * 4 + 1 1 + 2 3").iterator();
     Expr expr = Expr.parseExpr(it);
     System.out.println(expr);
     System.out.println(expr.eval());
    

  1. Dessinez l'arbre d'expressions créé par le code ci-dessus puis dessinez sur l'arbre l'évaluation de l'expression (c'est-à-dire un appel à la méthode eval()).
    Faite une photo du résultat.
  2. En lisant l'article wikipedia sur le Visitor Pattern (et sa section Java example), modifiez le code pour introduire le visiteur ExprVisitor, comme déclaré ci-dessous.
          public interface ExprVisitor {
            public int visitValue(Value value);
            public int visitBinOp(BinOp binOp);
          }
         

    Puis ecrivez une classe EvalExprVisitor qui effectue l'évaluation en utilisant le visitor pattern plutôt qu'en utilisant la méthode eval.
    Une fois que l'EvalExprVisitor fonctionne, supprimez la méthode eval de l'interface Expr (et des sous classes).
  3. On souhaite faire la même transformation mais avec la méthode toString à la place de la méthode eval. Comme toString retourne une String et pas un int comme eval, il faut paramétrer l'interface ExprVisitor par le type de retour comme ceci.
          public interface ExprVisitor<R> {
            public R visitValue(Value value);
            public R visitBinOp(BinOp binOp);
          }
         

    Modifiez votre code pour utiliser la version paramétrée de l'interface ExprVisitor ci-dessus.
    Vous pouvez utiliser la classe ElementVisitor comme modèle !
    Ecrivez une classe ToStringVisitor qui effectue le même travail que toString puis retirez les méthodes toString une fois que le visiteur marche.
  4. Le toStringVisitor que vous avez écrit (comme les méthodes toString qu'il y avait précédemment) n'est pas très efficace car il y a beaucoup de création de String intermédiaire, il serait préférable d'utiliser un seul StringBuilder pour tout le calcul.
    Modifiez le ToStringVisitor pour n'utiliser qu'un seul StringBuilder.
    Note: cela veut peut-être dire modifier l'interface ExprVisitor ou pas, il y a plusieurs solutions, essayer de venir avec la votre.

Exercice 3 - Le visiteur avec des lambdas

Revenons sur ce qu'est un visteur, un visteur est un objet qui associe à une classe (Value ou BinOp) un code à exécuter. Il peut donc être implanté avec une table de hachage qui associe à une classe (un objet de type java.lang.Class) une lambda contenant le code à exécuter.
On se propose d'écrire la classe ExprVisitor de tel sorte à ce que le code suivant fonctionne
     ExprVisitor<Integer> evalVisitor = new ExprVisitor<>();
     evalVisitor
       .when(Value.class, value -> {
         ...
       })
       .when(BinOp.class, binOp -> {
         ...
       });
     evalVisitor.call(expr); 
     

  1. Quel sont le ou les avantages de l'API proposée par rapport à une API de visiteur classique ?
  2. Quelle doit être la signature de la méthode when ?
    Quel est le type du second paramètre de la méthode when ?
  3. Quelle est la signature de la méthode call ?
  4. Quelle structure de donnée doit être utilisée pour implanter les méthodes when et call ?
    Ecrire en pseudo code, les codes de when et call.
    Comment déclarer la structure de données pour éviter de faire des casts ?
    Ecrire le code Java de la classe ExprVisitor.
  5. Quelle sont les avantages et inconvénients d'écrire le code du visiteur de cette façon là par rapport au visteur classique du GOF ?