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

Langage Java Discussion :

Conception : héritage et instanceof


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut Conception : héritage et instanceof
    Bonsoir,
    Supposons une classe mère abstraite Element disposant d'un certain nombre d'attributs, et dont dérivent les classes concrètes ElementA, ElementB, ElementC, chacune possédant ses attributs propres.
    On souhaite représenter dans un JPanel PanelElement les caractéristiques d'un objet sous-type d'Element.
    Quelle serait la façon la plus élégante et la plus "orientée objet" de définir la classe PanelElement, et éventuellement ses sous-types ?
    Par exemple (toute autre suggestion est la bienvenue...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    abstract class PanelElement extends JPanel {
      public PanelElement(Element element) {
        this.element = element;
        add(new JLabel("Date début"));
        add(new JLabel(String.valueOf(element.getDateDebut())));
        ...
      }
    }
     
    class PanelElementA extends PanelElement {
      public PanelElementA(ElementA elementA) {
        super(elementA);
        this.elementA = elementA;
        add(new JLabel("Heure début");
        add(new JLabel(String.valueOf(elementA.getHeureDebut())));
        ...
      }
    }
    Je précise que Element et ses sous-classes sont de simples business objects (beans) et qu'il n'est pas possible d'enrichir ses classes pour fournir d'autres méthodes que les getter/setter sur les attributs.
    Le problème est le suivant : je dispose d'une collection d'objets de type ElementA, ElementB, ...
    Comment instancier le panel correspondant en évitant des appels à instanceof ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if (element instanceof ElementA) {
      return new PanelElementA((ElementA) element);
    } else if (element instanceof ElementB) {
      ...
    }
    Si on est amené à créer un nouveau type ElementD, il faut prévoir son panel correspondant PanelElementD. Il est pénible d'avoir à rechercher dans le code les occurrences de instanceof ElementX pour compléter avec le nouveau type partout où c'est nécessaire...
    D'où la question : y a-t-il un design pattern ou des techniques OO permettant de s'affranchir tout ou partie de faire de la reconnaissance de type à l'exécution ?

  2. #2
    Membre averti
    Inscrit en
    Avril 2002
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 36
    Par défaut
    Je ne suis pas encore vraiment au top sur les design pattern, mais le cas qui te pose problème me semble pas mal adapté à se documenter sur les factory et les décorateurs ^^.

    Le concept qu'il te faudrait mettre en place est de déléguer à une classe tierce la responsabilité d'instancier le Panel adapté en fonction de l'objet courant.
    L'intérêt qui se présentera assez vite c'est que dans le cas de l'ajout d'un nouveau sous-type impliquera "uniquement" la création du nouveau bean et l'introduction de la prise en charge dans la côté Factory et la création de l'objet de vue correspondant.

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    319
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 319
    Par défaut
    Effectivement, le motif Factory serait utile ici.

    Autrement pour éviter les tests avec instanceof tu pourrais utiliser un tableau associatif liant des classes d'Element aux classes de Panel correspondants.

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class Herve91Factory
    {
        private Map<Class, Class> panelsByElement;
     
        public Herve91Facrtory()
        {
            panelsByElement = new HashMap<Class, Class>();
            panelsByElement.put(ElementA.class, PanelElementA.class);
            panelsByElement.put(ElementB.class, PanelElementB.class);
            ...
        }
     
        public PanelElement createPanel(Element element)
        {
            PanelElement panel = panelsByElement.get(element.getClass()).newInstance();
            ...
        }
     
        ...
     
    }

  4. #4
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Merci pour vos réponses, effectivement j'ai pensé à faire un tableau associatif, mais la solution que tu proposes TigRoO° ne fonctionne pas. En effet, si tu as bien regardé les constructeurs des classes PanelElementX, elles prennent en entrée un objet de type ElementX, donc il n'y a pas de constructeur par défaut.

    Voici ce à quoi j'ai pensé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class Herve91Factory {
        interface PanelFactory {
          PanelElement newInstance(Element element);
        }
    
        static class PanelAFactory implements PanelFactory {
           public PanelElement newInstance(Element element) {
              return new PanelElementA((ElementA) element);
           }
        }
        ...
    
        private Map<Class, PanelElementFactory> panelsByElement;
    
        public Herve91Factory()
        {
            panelsByElement = new HashMap<Class, PanelElementFactory>();
            panelsByElement.put(ElementA.class, new PanelAFactory());
            panelsByElement.put(ElementB.class, new PanelBFactory());
            ...
        }
     
        public PanelElement createPanel(Element element)
        {
            PanelElement panel = ((PanelElementFactory) panelsByElement.get(element.getClass())).newInstance(element);
            ...
        }
    }
    On a évité les tests avec instanceof, mais il y a toujours une conversion de type... bonne nouvelle quand même, elle est "encapsulée"...
    Si qq voit une solution encore plus générique

  5. #5
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Sinon en poussant plus loin dans la réflexion tu peux récupérer les Constructors de tes classes et instancier ta classe à partir de ceux ci

  6. #6
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Oui, je sais, mais je trouve dommage d'utiliser des mécanismes aussi lourds que la réflexion pour faire ça... SI on en arrive là, il me semble que ça traduit quand même une limite au concept d'héritage, non ?

Discussions similaires

  1. Héritage, getClass, instanceof, casting
    Par tichadok dans le forum Langage
    Réponses: 3
    Dernier message: 29/05/2008, 17h56
  2. [Conception] héritage et overriding
    Par DranDane dans le forum Algorithmes et structures de données
    Réponses: 5
    Dernier message: 11/02/2008, 10h48
  3. Conception: héritage d'une classe abstraite
    Par Kikito dans le forum Langage
    Réponses: 19
    Dernier message: 05/10/2006, 17h36
  4. [conception] Héritage comment faire ?
    Par bohor2gannes dans le forum Modélisation
    Réponses: 11
    Dernier message: 15/02/2006, 17h35
  5. [heritage][conception]héritage multiple en java!
    Par soulhouf dans le forum Langage
    Réponses: 9
    Dernier message: 25/08/2005, 20h03

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