Although you have already asked the Differences between listeners and adapters in the swing and also Listeners are an implementation of Observer? , I would like a more detailed explanation.
What are listeners in java? How to implement one?
Although you have already asked the Differences between listeners and adapters in the swing and also Listeners are an implementation of Observer? , I would like a more detailed explanation.
What are listeners in java? How to implement one?
As you've seen, "Listener" and "Observer" are different names for the same pattern , and , it can be used for several things beyond use in Swing, and can be implemented in several other languages. Within Java, for example, the JavaFX bindings system uses (internally) the Observer pattern by binding between Properties , which allows a Property to be changed (updated) when another is; and this system can be used even in softwares without Graphical Interface (you can use Properties and bindings even without a GUI).
It is common to use this pattern when you want a given code to be executed (the observer's code) when something happens (the event) in something (this "something" is the observed thing, button on the screen).
It is also common to use this standard to automatically update data (which is the case of JavaFX Properties and Bindings); in this case, you can have an implementation that ensures even data consistency from these automatic updates.
dataDeNascimento
attribute and a idade
attribute within a Pessoa
Object, and, when the value in dataDeNascimento
is changed, the value in idade
is automatically updated , in order to ensure% will always correctly match the date of birth. So if you call idade
and then call setDataDeNascimento(...)
you will get the age already updated (but be careful about competition issues, not read data that is not yet up to date or, in the case of long data structures being updated, reading the structure while it is still "half-updated"). The code below is a simple implementation to exemplify the Observer Pattern:
public class Observado {
private Object atributoQualquer;
private final List<Observador> observadores = new ArrayList<Observador>();
private void notificarObservadores() {
for (Observador observador : observadores) {
observador.notificar(this);
}
}
public void adicionarObservador(Observador obs) { //também chamado de addListener(...)
observadores.add(obs); //"obs" passará a ser notificado sobre mudanças em this
}
public void removerObservador(Observador obs) { //também chamado de removeListener(...)
observadores.remove(obs); //"obs" deixará de ser notificado sobre mudanças em this
}
public void setAtributoQualquer(Object novoValor) {
atributoQualquer = novoValor;
notificarObservadores(); //avisamos os Observadores que houve uma alteração em this
}
}
public interface Observador { //também chamado de "Listener"
public void notificar(Observado obs); //também chamado de "notify()"
}
public class ObservadorA implements Observador {
public void notificar(Observado obs) { //Chamado quando ocorrer uma alteração em "obs"
//Atualiza dados, executa código que deve ser executado quando "obs" for alterado, etc.
//Aqui dentro pode-se chamar GETTERS de "obs" para obter os novos dados em "obs", como chamar "obs.getAtributoQualquer()"
}
}
Having the code above, it is still necessary to register getIdade()
as an observer of ObservadorA
so that it can be notified when Observado
is changed, we can do it like this:
Observado observado = new Observado();
observado.adicionarObservador(new ObservadorA());
Done, that way the Observado
of notificar(...)
method will be called when ObservadorA()
is changed (changed when calling observado
).
Considerations for this Example:
I made a method setAtributoQualquer(...)
, this method signature causes the Observer to "pull" ( pull ) the data of notificar(Observado obs)
to know what was changed and what new values in obs
, this is done by calling the GETTERS of obs
.
The method could be, for example, obs
or notificar(Object novoValor)
or even notificar(Observado obs, Object novoValor)
, any of these would be pushing the data to the viewer, so that it does not have to call the GETTERS of notificar(Observado obs, Object novoValor, Object valorAnterior)
. Note: obs
signature is similar to notificar(Observado obs, Object novoValor, Object valorAnterior)
method signature of JavaFX% class:
changed(...)
It is common for Observers to add "Observers" for different types of events / changes, so you will find methods like ChangeListener
, void changed(ObservableValue<? extends T> observable, T oldValue, T newValue)
, etc. (for example, addXXXXListener()
, addYYYYListener()
, addFocusListener(...)
, etc.). This allows you to create codes to "hear" (or "observe") different things, without having to listen / observe everything that happens in the Observed object.
It is also very common to create Anonymous Classes and, more recently, Lambda Expressions , instead of creating Observer Classes, this reduces the amount of code, and is used directly in addActionListener(...)
methods. Examples:
addMouseListener(...)
addXXXXListener(...)
JavaFX has an Observer system that is very interesting, and goes far beyond what I presented here, I highly recommend Study it .
If we translate the word Listener into Portuguese we will have the word "Listener". Listener in the Portuguese language is defined as "He who hears".
We can define it as a listener too, because it stays as if it were aware of all user actions .
It waits, as if it were filtered all the data generated by the user (mouse movement, click the mouse, key pressed ...), then take the defined attitude.
If we were to assign synonyms to the Listener function we would assign the following words:
Listener
Receiver
Viewer
Helper
Observer
Perhaps because of the extension of the subject I recommend to read carefully the following matter which covers well this.
Example of a Listener interface:
public interface EventListener {
void fireEvent (Event e);
}
A video that might also be of help for the creation would be this: link
Listener has some peculiarities that make it difficult to explain by writing.