Una duda que me ha surgido.
En Java, ¿como veríais la mejor forma de realizar un callback?
Supongamos que tenemos una clase Interfaz y otra Controlador.
Pongamos que cuando se pica un botón la interfaz lanza un thread con controlador (pongamos que el propio controlador implementa run o runnable) y pone algún mensajito en pantalla de "Ocupado" y continúa con el bucle estándar de la interfaz gráfica.
El controlador, en su thread, ejecuta cierto código y genera algún resultado, y debe avisar a la interfaz (en este ejemplo) de que ya ha acabado.
A primera vista lo que podemos pensar hacer es lo típico: le paso mi instancia de "Interfaz" y que cuando acabe que llame a "interfaz.accionCompletada()", pero esto es muy warro, se acopla completamente con la clase Interfaz, si lo queremos reusar en otra cosa no nos vale / es una mierda.
Para esto podemos crear entonces una interface "interface ControladorCallback", y que Interfaz (y cualquier otra cosa que quiera obtener un callback) la implemente, vamos, un patrón observador, pero no me termina de convencer lo de tener que hacer que la clase implemente interfazs solo para poder recibir un simple callback.
He probado un posible ejemplo que pongo a continuación por si a alguien también le interesara, pero es muy simple:
spoilerTendríamos la interfaz de callbacks:
public interface CallBack {
public void callback();
}
Nuestra clase "Interfaz" que extendería esa par poder recibir los callbacks:
public class Interfaz implements CallBack {
private Controlador ctrl;
private boolean fin = false;
public Interfaz() {
ctrl = new Controlador(this);
ctrl.start();
}
@Override
public synchronized void callback() {
fin = true;
notify();
}
// Esta función solo tiene el propósito de ser usada por el Main para
// esperar a que se pueda acabar el programa.
public synchronized void esperar() throws InterruptedException {
while (!fin) {
System.err.println("Esperando");
wait();
}
}
}
Y el controlador que recibe el parámetro de a quien debe avisar (se podría cambiar a un vector y añadir diversos, obviamente), en funcionalidad solo espera y avisa de que ha acabado:
public class Controlador extends Thread {
private CallBack cb;
public Controlador(CallBack cb) {
this.cb = cb;
}
@Override
public void run() {
System.err.println("Run");
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cb.callback();
}
}
Un main simple que solo instancia y llama a esperar:
public class Main {
public static void main(String[] args) throws InterruptedException {
new Interfaz().esperar();
System.out.println("Final");
}
}
Sin embargo veo bastante más útil un sistema como el que utilizan algunas librerías de interfaces gráficas, en el que se instancian "Listeners" y se le van añadiendo al elemento a observar. Eso sin contar con una sola clase se pueden implementar todas las callbacks. Además de ser muy simple pasar del modelo anterior a este, solo hay que cambiar la forma de usar las interfazs.
De nuevo, dejo un pequeño código por si a alguien le interesa.
spoilerLa interfaz, controlador y main son los mismos, solo cambia la clase Interfaz, que ya no extiende a nada.
public class Interfaz {
private Controlador ctrl;
private boolean fin = false;
public Interfaz() {
ctrl = new Controlador(new CallBack() {
@Override
public void callback() {
hacerCosasWays();
}
});
ctrl.start();
}
public synchronized void hacerCosasWays() {
fin = true;
notify();
}
public synchronized void esperar() throws InterruptedException {
while (!fin) {
System.err.println("Esperando");
wait();
}
}
}
Pues eso, para los que tienen más experiencia. ¿Cual es la mejor forma veis de implementar un callback? ¿Alguna otra forma? ¿Usando alguna función de la API de Java que desconozco y que da solución a este problema?