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

Java Discussion :

Pattern cas particulier listeners?


Sujet :

Java

  1. #1
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut Pattern cas particulier listeners?
    Salut,

    Je recherche une "bonne manière de faire" dans un cas particulier d'utilisation des listeners.

    Dans la classe de l'observé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class MyXListened {
        public void addXListener(XListener listener) {
            xListeners.add(listener);
        }
     
        public void removeXListener(XListener listener) {
            xListeners.remove(listener);
        }
     
        protected void fireXXX() {
            for(XListener listener : listeners)
                listener.xxx(this);
        }
    }
    Jusqu'ici, tout va bien (ou presque)...

    Maintenant, dans la classe d'un écouteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MyXListener implements XListener {
        public void xxx(MyXListened source) {
            source.removeXListener(this);
        }
    }
    Forcément, cela va planter avec ce genre d'itérateur, avec un ConcurrentModificationException (la liste des écouteurs est modifiée alors qu'elle est parcourue). On pourrait utiliser une boucle for normale, avec des indices, mais le problème est le même, si on supprime un écouteur, ça décale tout...

    Comment faire pour que "ça marche bien", "proprement" ?

    J'ai pensé à ça, mais bon, je ne sais pas ce que ça vaut:
    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
    class MyXListened {
        public void addXListener(XListener listener) {
            xListeners.add(listener);
        }
     
        public void removeXListener(XListener listener) {
            xListeners.remove(listener);
        }
     
        protected void fireXXX() {
            Collection<XListener> listeners = new ArrayList<XListener>(xListeners);
     
            for(XListener listener : listeners)
                listener.xxx(this);
        }
    }
    Ou encore que la méthode xxx() renvoie un boolean indiquant si l'écouteur doit être supprimé (et dans ce cas là on supprime grâce à l'itérator)...


    Quelle est la "bonne manière"?

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Pourquoi ne pas utiliser la classe EventListenerList ? Elle est faite pour cela :
    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
    class MyXListened {
        private EventListenerList listeners = new EventListenerList();
     
        public void addXListener(XListener listener) {
            listeners.add(XListener.class, listener);
        }
     
        public void removeXListener(XListener listener) {
            listeners.remove(XListener.class, listener);
        }
     
        protected void fireXXX() {
            // getListeners() renvoit un tableau contenant les Listeners correspondant
            for (XListener listener : listeners.getListeners(XListener.class)) {
                listener.xxx(this);
            }
        }
    }
    La seule "contrainte" c'est que ton interface XListener doi étendre l'interface "marqueur" EventListener :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface XListener extends EventListener {
       ...
    }
    a++

  3. #3
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    C'est une autre solution, mais ça ne change rien au problème, le code de javax.swing.event.EventListenerList#getListeners(Class<T> t):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        public <T extends EventListener> T[] getListeners(Class<T> t) {
    	Object[] lList = listenerList; 
    	int n = getListenerCount(lList, t); 
            T[] result = (T[])Array.newInstance(t, n); 
    	int j = 0; 
    	for (int i = lList.length-2; i>=0; i-=2) {
    	    if (lList[i] == t) {
    		result[j++] = (T)lList[i+1];
    	    }
    	}
    	return result;   
        }
    Si un autre Thread ajoute un listener, ...



    Oups, j'avais pas vu, le #add() crée à chaque fois un nouvel Object[]... Donc ça marcherait, effectivement... Mais bon, c'est un peu lourd... je ne vois pas ce que EventListenerList apporte, je trouve que ça complique plutôt les choses, non? Peut-être uniquement l'avantage d'avoir un seul EventListenerList pour tous les écouteurs...

  4. #4
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Bon, finalement, après l'avoir testé, c'est vrai que ça simplifie bien les choses...

    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Effacer (cas particulier) d'un champ de formulaire
    Par frog43 dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 17/05/2006, 18h29
  2. Réponses: 27
    Dernier message: 12/01/2006, 11h04
  3. cas particulier agaçant
    Par devdébuto dans le forum C
    Réponses: 17
    Dernier message: 13/12/2005, 23h45
  4. Enregistrement courant après refresh [cas particulier]
    Par say dans le forum Bases de données
    Réponses: 8
    Dernier message: 02/08/2005, 15h59

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