Para criar nosso próprio listener, vamos imaginar um telefone. Possui método toca e atende e implementa eventos como tocou e atendido.
Para criar um Listener, primeiro temos que criar uma interface para nosso listener herdando de EventListener
TelefoneListener
public interface TelefoneListener extends java.util.EventListener {
void telefoneTocou(TelefoneEvent e);
void telefoneAtendido(TelefoneEvent e);
}
Criaremos também um Event para que possamos saber qual "telefone" está chamando o evento
TelefoneEvent
public class TelefoneEvent extends java.util.EventObject {
public TelefoneEvent(Telefone source) {
super(source);
}
}
Um adapter nos ajuda para caso queiramos implementar apenas um dos métodos do Listener sem precisar deixar os demais vazios
TelefoneAdapter
public class TelefoneAdapter implements TelefoneListener {
public void telefoneTocou(TelefoneEvent e) {}
public void telefoneAtendido(TelefoneEvent e) {}
}
Agora implementamos o telefone propriamente dito, este terá o método addTelefoneListener
Telefone
import java.util.ArrayList;
import java.util.Collection;
public class Telefone {
private Collection <TelefoneListener> telefoneListeners = new ArrayList<TelefoneListener>();
// método de suporte para testar a solução
public void tocaFone() {
disparaTelefoneTocou();
}
// método de suporte para testar a solução
public void atendeFone() {
disparaTelefoneAtendido();
}
public synchronized void addTelefoneListener(TelefoneListener l) {
if(!telefoneListeners.contains(l)) {
telefoneListeners.add(l);
}
}
public synchronized void removeTelefoneListener(TelefoneListener l) {
telefoneListeners.remove(l);
}
private void disparaTelefoneTocou() {
Collection <TelefoneListener> tl;
synchronized (this) {
// Clonar para evitar problemas de sincronização
// durante a propagação
tl = (Collection)(((ArrayList)telefoneListeners).clone());
}
TelefoneEvent evento = new TelefoneEvent(this);
for (TelefoneListener t : tl) {
t.telefoneTocou(evento);
}
}
// disparaTelefoneAtendido() é semelhante a disparaTelefoneTocou()
// Exercício: Que design pattern poderia ser usado para fatorar o código comum?
private void disparaTelefoneAtendido() {
Collection <TelefoneListener> tl;
synchronized (this) {
tl = (Collection)(((ArrayList)telefoneListeners).clone());
}
TelefoneEvent evento = new TelefoneEvent(this);
for (TelefoneListener t : tl) {
t.telefoneAtendido(evento);
}
}
}
Para testar, vamos criar 2 classes que utilizam o telefone, sendo que cada uma se utiliza de uma maneira diferente do listener que criamos
SecretariaEletronica
public class SecretariaEletronica implements TelefoneListener {
public void telefoneTocou(TelefoneEvent e) {
System.out.println("Secretaria escuta o telefone tocando.");
}
public void telefoneAtendido(TelefoneEvent e) {
System.out.println("Secretaria sabe que o telefone foi atendido.");
}
}
Pessoa
public class Pessoa {
public void escutaTelefone(Telefone t) {
t.addTelefoneListener(
new TelefoneAdapter() {
public void telefoneTocou(TelefoneEvent e) {
System.out.println("Eu pego!");
((Telefone)(e.getSource())).atendeFone();
}
}
);
}
}
Teste (main)
public class Teste {
public static void main(String[] args) {
Telefone fone = new Telefone();
Pessoa fulano = new Pessoa();
SecretariaEletronica se = new SecretariaEletronica();
fone.addTelefoneListener(se);
fulano.escutaTelefone(fone);
fone.tocaFone(); // começa a brincadeira
}
}
Saída
Secretaria escuta o telefone tocando.
Eu pego!
Secretaria sabe que o telefone foi atendido.
Saida mais
http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/arqu/observer.htm