Domanda

Sto utilizzando l'interfaccia Observable class/Observer in Java per implementare il modello dell'osservatore.L'interfaccia Observer richiede la sovrascrittura del metodo update(Observable o, Object arg).

Il problema è che sto osservando un discreto numero di classi e il mio metodo update() è diventato molto 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) {
            ...
        }
    }

}

Per suddividere il metodo, sto pensando di estendere l'interfaccia dell'Observer con ad es.Interfaccia AObserver, interfaccia BObserver..che richiede la sovrascrittura onAUpdate, onBUpdate ..rispettivamente.Questo metodo consentirà inoltre di determinare facilmente quali oggetti osservabili la classe sta osservando in base alle interfacce che sta implementando.

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
        ...
    }
}

Il problema è che se eredito Observer, devo comunque implementare il metodo update().Non posso rinominarlo in onAUpdate o con un altro nome di mia scelta.

Qualche consiglio?Grazie.

È stato utile?

Soluzione

Qui ho codificato un'implementazione grezzo utilizzando osservatore ed il modello visitatore. Si può prendere questo come idea per migliorare su di essa e per riempire ovunque vedete alcuni fori.

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();
    }

}

Spero che non sono persi. :)

Altri suggerimenti

Suggerirò di creare un'interfaccia UpdateHandler per eseguire l'elaborazione per ogni determinato blocco di codice.Ogni caso può essere gestito con una mappa.

Segue il codice di esempio:

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

Aggiungi un campo di istanza alla tua classe principale come segue:

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

Creare un metodo per inizializzare i gestori

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

Il metodo degli aggiornamenti troverà semplicemente il gestore appropriato e invierà la chiamata

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) ;
    }
}

Questa implementazione ti consentirà di aggiungere un nuovo gestore secondo necessità con modifiche minime.

Un'altra possibile implementazione può essere eseguita sulla base del lavoro precedente, con una procedura in soli 3 passaggi.

1) Modificare la dichiarazione del campo handler.

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

2) cambiare il metodo di inizializzazione

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

3) modificare il metodo di aggiornamento principale per creare una nuova istanza dell'implementazione UpdateHandler fornita.

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

Spostare i pezzi di codice all'interno di ogni condizione di metodi nome appropriato.

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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top