2010-11-24 14 views
5

Estoy usando la clase observable/interfaz Observer en Java para implementar el patrón de observador. La interfaz Observer requiere sobrescribir el método de actualización (Observable o, Object arg).Cambiar el nombre de los métodos implementados para el patrón Observer en Java

El problema es que estoy observando un buen número de clases, y el método de mi actualización() se ha hecho muy grande:

public class Foo implements Observer { 
    .... 

    public void update(Observable o, Object param) { 
     if (o instanceof A) { 
      // large chunk of code 
      ... 
     } else if (o instanceof B) { 
      // large chunk of code 
      ... 
     } 
      ... 
     } else if (o instanceof H) { 
      ... 
     } 
    } 

} 

Con el fin de dividir el método, estoy pensando en extender la interfaz Observer con, por ejemplo, Interfaz de AObserver, interfaz BObserver ... que requiere sobreescritura onAUpdate, onBUpdate ... respectivamente. Este método también facilitará determinar qué observables está observando la clase en función de las interfaces que implementa.

class Foo implements AObserver, BObserver { 
    .... 

    public void onAUpdate(Observable o, Object param) { 
     if (o instanceof A) { 
     // large chunk of code 
     ... 
    } 

    public void onBUpdate(Observable o, Object param) { 
     if (o instanceof B) { 
     // large chunk of code 
     ... 
    } 
} 

El problema es que si he heredado Observer, todavía tengo que implementar el método update(). No puedo cambiarle el nombre a onAUpdate ni a ningún otro nombre de mi elección.

¿Algún consejo? Gracias.

Respuesta

1

Aquí codifiqué una implementación sin procesar con un patrón de observador y visitante. Puedes tomar esto como una idea para realzarlo y llenarlo donde veas algunos agujeros.

public interface IObserver extends Observer { 
    public void add(AbstractObservable observable, IObserverVisitor visitor); 
    public void remove(AbstractObservable observable); 
    public void removeAll(); 
} 

public class Observer implements IObserver { 

    Map<AbstractObservable, IObserverVisitor> observableMap = 
      new HashMap<AbstractObservable, IObserverVisitor>(); 

    public void add(AbstractObservable observable, IObserverVisitor visitor) { 
     observableMap.put(observable, visitor); 
    } 

    public void remove(AbstractObservable observable) { 
     observableMap.remove(observable); 
    } 

    public void removeAll() { 
     observableMap.clear(); 
    } 

    public void update(Observable o, Object arg) { 
     observableMap.get(o).visit(this, o, arg); 
    } 

} 

public class AbstractObservable extends Observable{ 

    public synchronized void addObserver(IObserver o, IObserverVisitor visitor) { 
     o.add(this, visitor); 
     super.addObserver(o); 
    } 

    public synchronized void deleteObservers(IObserver o) { 
     o.removeAll(); 
     super.deleteObservers(); 
    } 

    public synchronized void deleteObserver(IObserver o) { 
     o.remove(this); 
     super.deleteObserver(o); 
    } 

    @Override 
    public synchronized void deleteObserver(Observer o) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public synchronized void addObserver(Observer o) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public synchronized void deleteObservers() { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public synchronized int countObservers() { 
     return super.countObservers(); 
    } 

    @Override 
    public synchronized boolean hasChanged() { 
     return super.hasChanged(); 
    } 

    @Override 
    public void notifyObservers() { 
     super.notifyObservers(); 
    } 

    @Override 
    public void notifyObservers(Object arg) { 
     super.notifyObservers(arg); 
    } 

    @Override 
    protected synchronized void clearChanged() { 
     super.clearChanged(); 
    } 

    @Override 
    protected synchronized void setChanged() { 
     super.setChanged(); 
    } 

} 

public class Observable1 extends AbstractObservable { 
    public void changeSomething() { 
     setChanged(); 
     notifyObservers(); 
    } 
} 

public class Observable2 extends AbstractObservable { 
    public void changeSomething() { 
     setChanged(); 
     notifyObservers(); 
    } 
} 

public interface IObserverVisitor { 
    void visit(IObserver obsrvr, Observable obsrvable, Object o); 
} 

public class ObserverVisitor1 implements IObserverVisitor{ 

    public void visit(IObserver obsrvr, Observable obsrvable, Object o) { 
     System.out.println("updated one"); 
    } 

} 

public class ObserverVisitor2 implements IObserverVisitor{ 

    public void visit(IObserver obsrvr, Observable obsrvable, Object o) { 
     System.out.println("updated two"); 
    } 
} 

public class ObserverTest { 

    @Test 
    public void testAnything() { 
     Observable1 obsrvable1 = new Observable1(); 
     Observable2 obsrvable2 = new Observable2(); 

     Observer obsrvr = new Observer(); 
     obsrvable1.addObserver(obsrvr, new ObserverVisitor1()); 
     obsrvable2.addObserver(obsrvr, new ObserverVisitor2()); 

     obsrvable1.changeSomething(); 
     obsrvable2.changeSomething(); 
    } 

} 

espero que no se pierdan. :)

+0

Gracias, esta es una buena solución. No estoy seguro si es directamente adecuado para mi situación, podría tener que adaptar algunas partes, pero me dio algunas buenas ideas. –

+0

@David: Me alegra que lo encuentre útil. Mis esfuerzos no fueron desperdiciados. ;) –

1

Mueva los trozos de código dentro de cada condición a los métodos apropiadamente nombrados.

public void update(Observable o, Object param) { 
    if (o instanceof A) { 
     onAUpdate(o, param); 
    } 

    if (o instanceof B) { 
     onBUpdate(o, param); 
    } 
} 

public void onAUpdate(Observable o, Object param) { 

    // large chunk of code 
} 

public void onABUpdate(Observable o, Object param) { 

    // large chunk of code 
} 
+0

¿Es posible implementar una interfaz para cada Observable? Se vuelve mucho más claro determinar en qué objetos está interesado mi clase cuando implementa AObserver, BObserver ... en lugar de solo un Observer genérico –

+0

Eso es lo que estaba haciendo originalmente. Usted acaba de sugerir sacar el pedazo para separar los métodos. El código todavía huele. –

+0

Dijo el problema como "mi método update() se ha vuelto muy grande". – crnlx

3

Sugiero crear una interfaz UpdateHandler para hacer el procesamiento para cualquier bloque de código dado. Cada caso se puede manejar con un mapa.

El código de ejemplo siguiente:

// Interface to implement for each case 
public interface UpdateHandler { 
    public void update(Observable source, Object data) ; 
} 

Añadir un campo de instancia a la clase principal de la siguiente manera:

private Map<Class<?>, UpdateHandler> handlers = new HashMap<Class<?>, Update Handler>(); 

crear un método para que los manipuladores inicializan

protected void initializeHandler() { 
    handler.put(Integer.class, new IntegerUpdateHandler()); 
    handler.put(String.class, new StringUpdateHandler()); 
    ... 
} 

Las actualizaciones método simplemente encontrará el controlador apropiado y enviará la llamada al

public void update(Observable source, Object data) 
{ 
    UpdateHandler handler = handlers.get(data.getClass()) ; 
    if (handler == null) 
    { 
     // use a default handler ? throw an exception ? your choice ;) 
    } else { 
     handler.update(source, data) ; 
    } 
} 

Esta implementación le permitirá agregar un nuevo controlador según sea necesario con cambios mínimos.

Otra posible implementación se puede hacer en base al trabajo anterior, solo un procedimiento de 3 pasos.

1) Cambie la declaración del campo de controladores.

Map<Class<?>, Class<? extends UpdateHandler>> handlers ;

2) cambiar el método initialize

handlers.put(Integer.class, IntegerInputHandler.class);

3) cambiar el método de actualización principal para crear una nueva instancia de la aplicación UpdateHandler proporcionado.

UpdateHandler handlerInstance = null ; 
Class<? extends UpdateHandler> handler = null ; 
handler = handlers.get(data.getClass()) ; 
... 
handlerInstance = handler.newInstance() ; 
handlerInstance.update(source, data) ; 
+0

Tengo varios objetos observando lo observable. Cuando sucede algo interesante, cada clase que observa lo observable se comporta de manera diferente. Por ejemplo, si Foo y Bar observan A, cuando A cambia, Foo hace esto, Bar hace eso. El uso de esta solución, ¿no significa que tengo que crear un controlador para cada objeto para manejar las actualizaciones por separado, p. FooAHandler, BarAHandler? –

+0

@David: Si ese es el caso, no necesitas nada especial. El predeterminado 'Observable' y' Observer' harán la cosa. En la publicación original está comprobando el tipo de su 'Observable', que sugiere que un solo' Observer' está observando múltiples 'Observable'. –

+0

Es una relación de muchos a muchos: varios observadores están observando múltiples Observables. –

Cuestiones relacionadas