IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Design Patterns Discussion :

N'est-il pas un peu "sale" ?


Sujet :

Design Patterns

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut N'est-il pas un peu "sale" ?
    Bonjour,

    Cela fait un petit moment que je m'interroge sur le DP décorateur le trouvant un peu "sale".
    Je n'ai pas vraiment de problèmes avec les autres DPs (à part le visiteur que je préfère éviter quand je peux), mais je bloque un peu pour le DP décorateur.

    Déjà parce que je trouve sa syntaxe un peu lourde surtout si on a plusieurs décorateurs (1) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MaClasse A = new DecorateurA( new DecorateurB( new DecorateurC( new ConcreteClasse ) ) );
    A partir d'un certain nombre de décorateur, cela devient illisible.

    Ensuite, parce que ajouter un décorateur change "l'instance" (2) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Chevalier a = new ConcreteChevalier;
    //....
    Chevalier b = new DecorateurBouclier(a);
    a n'est pas la même chose que b.
    Si on a des références sur a dans le code, si on rajoute un décorateur, soit il faut mettre à jour toute ces références soit on va utiliser a comme un chevalier dans un bout de code et comme un "Chevalier avec bouclier" ailleurs dans le code .

    De plus, le fait de ne pas pouvoir retirer un décorateur me semble pas "génial" (3).


    Je ne comprend donc pas pourquoi on a pas :
    • ConcreteChevalier héritant de/implémentant X ;
    • Decorateur héritant de/implémentant X ;
    • et une classe Chevalier se comportant comme un "proxy".


    Grosso-modo avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Chevalier a = new Chevalier; // en interne créé un ConcreteChevalier
    for( int i = 0; i < NB ; ++i) // exemple
         a.add( decorateurs[i] );
    C'est à dire presque considérer Chevalier comme un "container" de Decorateurs ayant pour dernier élément un ConcreteChevalier.
    Je résous donc les problèmes 1,2 et 3.

    De plus, je trouve que c'est plus intuitif pour un utilisateur.
    Par exemple, quand on débute en Java et qu'on veut utiliser des fichiers, on ne comprend pas trop si on ne connaît pas le DP décorateurs.
    Alors qu'une syntaxe : Fichier( ConcreteFile cf, Filtre f...); me semble bien plus claire (Filtre = Décorateur).

    Pourquoi le DP décorateur est-il donc tel qu'il est ? Est-ce que je passe à côté de quelque chose ?
    En effet, si en Java on les utilise pour les I/O, et qu'on l'a intégré dans les DPs, je pense qu'il y a bien une raison.

  2. #2
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Par défaut
    Décorateur est utilisé quand on veut greffer une gamme de comportements optionnels et cumulatifs à une classe de base. Utiliser l'héritage pur serait peu pratique, car on devrait écrire autant de sous-classes que de combinaisons de comportements possibles.

    Le style de code qui découle de l'utilisation de Décorateurs peut paraitre répétitif car il reflète cette cumulativité. Pour autant, on n'est pas obligé de déclarer toutes les variables intermédiaires, on peut avoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Chevalier c = new DecorateurEpee( new DecorateurBouclier( new Chevalier()));
    A la base, le pattern Décorateur ne transforme pas un objet au runtime, parce qu'on n'en a pas vraiment besoin. Comme tu le dis, soit la classe cliente a une référence précise vers un objet décoré et n'aura jamais besoin de le re-décorer (90% des cas d'après mon expérience), soit s'il change, on lui repasse une nouvelle instance. Par contre, c'est inexact de dire que l'objet décoré est une instance totalement différente, car il contient une référence à l'objet d'origine, et non une copie de celui-ci.

    Ton système est plus dynamique et, peut-être, plus adapté pour un jeu où l'objet Chevalier va être transformé au cours du temps, acquérant des armes, des pouvoirs, subissant des effets... Mais ce n'est pas un Décorateur. Et il est aussi plus "dangereux", plus complexe et plus difficile à debugger puisqu'on peut ajouter et retirer à loisir des décorations. On peut être confronté à des situations compliquées lorsque plusieurs clients essaient de décorer / dé-décorer le même objet dans le même laps de temps.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Merci pour votre réponse.


    A la base, le pattern Décorateur ne transforme pas un objet au runtime, parce qu'on n'en a pas vraiment besoin. Comme tu le dis, soit la classe cliente a une référence précise vers un objet décoré et n'aura jamais besoin de le re-décorer (90% des cas d'après mon expérience), soit s'il change, on lui repasse une nouvelle instance. Par contre, c'est inexact de dire que l'objet décoré est une instance totalement différente, car il contient une référence à l'objet d'origine, et non une copie de celui-ci.
    Disons que ce n'est pas exactement la même chose, si on a :
    Classe a = new ConcreteClasse();
    Classe b = new Decorateur(a);
    Utiliser a ou b, ce n'est pas la même chose, ce n'est pas le même comportement.
    Avec a, on court-circuite le décorateur.


    Mais ce n'est pas un Décorateur.
    Pourtant, on peut arriver au même résultat, non?

    Et il est aussi plus "dangereux", plus complexe et plus difficile à debugger puisqu'on peut ajouter et retirer à loisir des décorations.
    Rien n'oblige de permettre le retrait d'un décorateur si cela pose problème, si on le permet, c'est une fonctionnalités supplémentaire.
    Pour l'ajout, on peut avoir le même problème avec le DP décorateur je pense.

    On peut être confronté à des situations compliquées lorsque plusieurs clients essaient de décorer / dé-décorer le même objet dans le même laps de temps.
    Là c'est le problème "safe-thread", je pense que c'est un peu HS ici vu que cela est un détail d'implémentation et qu'on peut rendre le tout safe-thread assez aisément.


    Mais oui, je commence à comprendre un peu mieux.
    Par contre, cela veut dire qu'il faut faire attention à bien utiliser le DP Décorateur correctement et faire toute la décoration au même "endroit". Je trouve que c'est relativement dangereux.

  4. #4
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Pourtant, on peut arriver au même résultat, non?
    On peut bien sûr arriver au même résultat, mais avec des différences dans l'utilisation et des fonctionnalités en plus dans ce que tu proposes. Personnellement, je trouve la forme monobjet.add(decorateur) moins révélatrice que new Decorateur(monobjet) qui indique bien qu'on va enrober l'objet d'origine avec une nouvelle couche de fonctionnalités, mais c'est un point de vue.

    Citation Envoyé par Neckara Voir le message
    Là c'est le problème "safe-thread", je pense que c'est un peu HS ici vu que cela est un détail d'implémentation et qu'on peut rendre le tout safe-thread assez aisément.
    Je ne parlais pas forcément d'un contexte multi-thread, mais d'un accès partagé à l'objet de manière générale. Avec ta solution, c'est possible que deux clients qui ont une référence au même objet décoré soient tentés de le re-décorer dans leur coin. Puisque si j'ai bien compris, la liste des décorations est une chaine dont le point d'entrée est forcément le dernier ajouté, cela affecte alors l'autre client qui n'a rien demandé à personne. Avec la solution classique, ça ne peut pas arriver. Je ne dis pas que ça se produira tout le temps, mais il y a un risque. On introduit aussi la notion de temporalité, l'ordre de décoration par les différents consommateurs compte : quel objet a ajouté une décoration en dernier ? Quand on tombe dans ce genre de cas, c'est beaucoup plus difficile de raisonner sur ce qui se passe au runtime : on est obligé de debugger et c'est souvent pénible.

    Citation Envoyé par Neckara Voir le message
    Par contre, cela veut dire qu'il faut faire attention à bien utiliser le DP Décorateur correctement et faire toute la décoration au même "endroit". Je trouve que c'est relativement dangereux.
    Pourquoi au même endroit ? Ce n'est pas une obligation. Deux consommateurs peuvent avoir, à des moments différents, besoin du même objet décoré différemment. Le pattern ne l'empêche pas. Et pourquoi dangereux ?

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Si l'objet est décoré différemment dans deux consommateurs, c'est très dangereux dans le sens où les comportements vont être indéterminés, si on a des buffers par exemple.

    De plus, un décorateur peut "garantir un certain état", état qui ne sera plus garanti car on le court-circuitera.
    Court-circuiter un décorateur en place me semble "dangereux" non?

    Le fait qu'une décoration affecte toute les instances me semble plus "logique".
    Après, il y a en effet une certaine temporalité, mais cela ne me choque pas tant que cela.

  6. #6
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Billets dans le blog
    2
    Par défaut
    Je ne comprend pas bien ton problème.
    Un décorateur est un objet X si X décrit les types d'objets que tu veux manipuler.
    On peut décorer le même objet concret x de type X dans 2 contextes différents car on aura des usages différents.
    Ce pattern est vraiment très utilisé.

Discussions similaires

  1. Réponses: 3
    Dernier message: 11/10/2011, 10h17
  2. premier pas... un peu bizarre
    Par gaia-harastra dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 10/01/2006, 10h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo