2010-04-30 4 views

Répondre

15

Semble que vous voulez envelopper un booléen dans une classe sur laquelle vous pouvez écouter les changements.

class ObservableBoolean { 

    // "CopyOnWrite" to avoid concurrent modification exceptions in loop below. 
    private final List<ChangeListener> listeners = 
      new CopyOnWriteArrayList<ChangeListener>(); 

    private boolean value; 

    public boolean getValue() { 
     return value; 
    } 

    public synchronized void setValue(boolean b) { 
     value = b; 
     for (ChangeListener cl : listeners) 
      cl.stateChanged(new ChangeEvent(this)); 
    } 

    public synchronized void addChangeListener(ChangeListener cl) { 
     listeners.add(cl); 
    } 

    public synchronized void removeChangeListener(ChangeListener cl) { 
     listeners.remove(cl); 
    } 
} 

Puis simplement faire:

ObservableBoolean b = new ObservableBoolean(); 

//... 

// Start the "period of time": 
b.addChangeListener(iWantToBeNotifiedOfChanges); 

// ... 

// End the "period of time": 
b.removeChangeListener(iWantToBeNotifiedOfChanges); 

Ceci est en fait un cas simple du modèle MVC (et le modèle d'observateur). Le modèle dans ce cas est le ObservableBoolean et la vue serait la "vue" qui veut être avertie des changements.

Vous pouvez aussi écrire votre propre interface ChangeListener si vous voulez éviter une étrange recherche javax.swing... importation

+0

+1 pour le modèle d'observateur. Je me demande si vous voulez surveiller le booléen lui-même, ou si vous devriez plutôt avoir la classe qui change d'état posséder la liste des écouteurs, et déclencher les événements de changement quand il effectue le mod sur le booléen. – akf

+0

@aioobe -> voir mon edit maintenant – Xorty

+1

+1 ... mais quelques points: la liste des listeners devrait probablement être finale, getValue() n'est pas synchronisée, Si un auditeur tente de se retirer en tant qu'auditeur à une exception ConcurrentModificationException. Vous pouvez résoudre ce dernier problème en utilisant un CopyOnWriteArrayList au lieu de ArrayList. – Adamski

1

utilisation Timer ou écrivez votre propre classe extension Thread.

recherche sur Google ces choses devrait vous donner un bon départ

modifier: De la question, il est pas tout à fait clair quelles sont ses intention. Peut-être qu'il veut invoquer une méthode dans la période exacte, pas immédiatement après l'événement. Pour ce modèle, je préfère toujours m'en tenir à la minuterie, ou écrire mon propre thread. Écrire son propre thread est toujours le meilleur moyen d'interpréter les besoins spécifiques des utilisateurs. D'un autre côté, si c'est vraiment le cas d'écouter des événements, mon modèle Timer serait complètement faux. Exemple: Je veux mettre à jour la base de données (imaginez un jeu par navigateur Web) toutes les 5 minutes, si les utilisateurs le demandent (reques = true). Avec une fausse requête, je n'ai pas besoin de mettre à jour la base de données. La mise à jour immédiate de la base de données (c'est-à-dire les statistiques dans le jeu Tribal Wars avec des milliers de joueurs) est totalement exagérée.

+1

Un rapide changé de vrai -> faux -> vrai passerait inaperçu à moins que vous n'embrassiez le booléen dans une certaine classe "check-if-changed-since-last-pall". – aioobe

+0

vrai, mais la question n'était pas de vérifier immédiatement, mais dans un certain laps de temps (période de temps). Cela dépend de la conception du modèle. Extension de la classe Thread est essentiellement l'implémentation des écouteurs (pas littéralement, mais presque même) – Xorty

+0

"si une modification est effectuée au cours de cette période, effectuez une méthode". Je dis, que si * deux * changements sont faits au cours de cette période, vous * avez * besoin d'un 'stateHasChanged' booléen supplémentaire qui garde une trace de ceci (sinon il est tout à fait possible que le changement passe inaperçu). – aioobe

-2

On dirait que vous devriez chercher à implémenter une sorte de Model View Controller Pattern. Jetez un oeil here

L'idée de base est que vous devriez déclencher un événement lorsque le booléen est modifié, puis cet événement est déclenché, votre auditeur doit gérer cela.

+0

Ehm, pourquoi voter vers le bas ?? –

6

La meilleure façon de le faire est avec une classe wrapper ...

public class Bool 
{ 
    public Bool(){ _val = false; } 
    public Bool(boolean val) { _val = val; } 

    public boolean getValue(){ return _val; } 
    public void setValue(boolean val){ 
     _changesupport.firePropertyChange("value",_val,_val=val); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener){ 
     _changesupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener){ 
     _changesupport.removePropertyChangeListener(listener); 
    } 

    private boolean _val = false; 
    private final PropertyChangeSupport _changesupport = new PropertyChangeSupport(this); 
} 

Ceci est un modèle commun dans Swing, et vous pouvez utiliser PropertyChangeSupport pour simplifier la création d'objets sur lesquels vous pouvez observer et écouter les changements de propriété. Avec ces classes, vous pouvez enregistrer un PropertyChangeListener pour gérer le résultat PropertyChangeEvent qui en résulte.

+0

Nice avec le 'PropertyChangeSupport'. Pourquoi n'est-il pas situé dans un paquet plus «générique»? – aioobe

+0

+1 pour PropertyChangeSupport. Bien que je voudrais juste le rendre final et public et passer les méthodes d'ajout et de suppression sur la classe Bool. –

Questions connexes