Crear un evento en java
javaUna clase es fuente de un evento y una o más clases pueden declararse como oyentes de ese evento. Estas clases oyentes pueden ser de los tipos más dispares, pero todas ellas deben implementar la interfaz que las define como posibles oyentes del evento. En este ejemplo, esta interfaz se llamará VariableChangeListener:
Si deseas que el objeto de estado del evento proporcione más información, te haces una subclase de ésta y ya está.
La interfaz Listener podría definir tantos métodos como eventos distintos pudiesen diferenciarse. En caso de haber un número excesivo de eventos, sería interesante crear una clase adaptadora. Pero no me meto en este jardín, porque nuestra interfaz sólo define un método.
Así que todas las clases que quieran apuntarse como oyentes del evento tendrán que implementar esta interfaz.
Por ejemplo, la clase MiClase quiere atender a eventos de este tipo:
La clase fuente de evento debe implementar dos métodos para registrar y desregistrar oyentes del evento. El registro de un oyente,
También implementa un método protegido (sólo lo llama la propia clase fuente o una hipotética subclase) al que se llama desde cualquier método que modifique el valor de la variable a controlar cuando supere el valor límite: notifyVariableChanged.
Te pongo la clase:
import java.util.*;
public interface VariableChangeListener {
public void variableChanged(EventObject e);
}
Como puedes ver, esta interfaz sólo obliga a implementar un método, variableChanged, al que se llamará cuando se lance el evento. Este método recibe un único argumento, de tipo java.util.EventObject, que representa un objeto de estado de evento. Su función es identificar al objeto fuente del evento.Si deseas que el objeto de estado del evento proporcione más información, te haces una subclase de ésta y ya está.
La interfaz Listener podría definir tantos métodos como eventos distintos pudiesen diferenciarse. En caso de haber un número excesivo de eventos, sería interesante crear una clase adaptadora. Pero no me meto en este jardín, porque nuestra interfaz sólo define un método.
Así que todas las clases que quieran apuntarse como oyentes del evento tendrán que implementar esta interfaz.
Por ejemplo, la clase MiClase quiere atender a eventos de este tipo:
public class MiClase implements VariableChangeListener {
...
// En algún método esta clase se registra como oyente
Variable var;
...
var.addVariableChangeListener(this);
// Debe implementar el método definido por la interfaz
public void variableChanged(EventObject evt) {
// Y actuar en consecuencia al dispararse el evento
}
...
}
Bueno, y ahora queda lo divertido, que es implementar la clase fuente del evento. Es muy facilote, verás: esta clase tiene una única variable miembro (aquella cuyo valor queremos controlar). Cuando se le dé a esta variable un valor superior al límite establecido, se disparará el evento.La clase fuente de evento debe implementar dos métodos para registrar y desregistrar oyentes del evento. El registro de un oyente,
addVariableChangeListener, se limita a agregar al mismo (un objeto que, recordemos, implementa la interfaz antes definida) a una lista de oyentes. El desregistro, removeVariableChangeListener, obviamente elimina al oyente de tal lista (un objeto podría querer dejar de ser notificado de ese evento).También implementa un método protegido (sólo lo llama la propia clase fuente o una hipotética subclase) al que se llama desde cualquier método que modifique el valor de la variable a controlar cuando supere el valor límite: notifyVariableChanged.
Te pongo la clase:
import java.util.*;
public class Variable {
private static int LIMITE_SUP;
private int variable;
private List listeners = new ArrayList();
// Métodos accesores
public void setVariable(int variable) {
this.variable = variable;
if (this.variable > LIMITE_SUP)
notifyVariableChanged();
}
public int getVariable() {
return this.variable;
}
// Métodos de registro/desregistro de oyentes
public synchronized void addVariableChangeListener(VariableChangeListener listener) {
listeners.add(listener);
}
public synchronized void removeVariableChangeListener(VariableChangeListener listener) {
listeners.remove(listener);
}
// Método de notificación de evento
protected void notifyVariableChanged() {
List lst;
EventObject evt = new EventObject(this);
synchronized(this) {
lst = (List)((ArrayList)listeners).clone();
}
for (Iterator it = lst.iterator() ; it.hasNext() ; )
((VariableChangeListener)it.next()).variableChanged(evt);
}
}
Un breve comentario sobre los métodos de registro/desregitro y el de notificación de evento: los dos primeros son sincronizados, porque se supone que se les puede invocar desde distintos objetos simultáneamente y hay que evitar pollos. El último parece complicado, pero no lo es en absoluto: se limita a invocar al método variableChanged sobre todos los objetos que hay en la lista de oyentes registrados. Pero no recorre esa lista directamente, sino un clon de la misma. Así, no hay problemas si, por ejemplo, estamos recorriendo el iterador procedente de la lista y se nos registra o desregistra un nuevo objeto como oyente del evento.